2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2020 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this program. If not, see
16 # <http://www.gnu.org/licenses/>.
19 from copy import deepcopy
20 from datetime import datetime
21 from datetime import timedelta
22 from importlib import import_module
23 from io import BytesIO
24 from operator import attrgetter
25 from os import environ
26 from os import urandom
27 from random import random
28 from string import ascii_letters
29 from string import digits
30 from string import printable
31 from string import whitespace
32 from time import mktime
34 from unittest import TestCase
36 from hypothesis import assume
37 from hypothesis import given
38 from hypothesis import settings
39 from hypothesis.strategies import binary
40 from hypothesis.strategies import booleans
41 from hypothesis.strategies import composite
42 from hypothesis.strategies import data as data_strategy
43 from hypothesis.strategies import datetimes
44 from hypothesis.strategies import dictionaries
45 from hypothesis.strategies import integers
46 from hypothesis.strategies import just
47 from hypothesis.strategies import lists
48 from hypothesis.strategies import none
49 from hypothesis.strategies import one_of
50 from hypothesis.strategies import permutations
51 from hypothesis.strategies import sampled_from
52 from hypothesis.strategies import sets
53 from hypothesis.strategies import text
54 from hypothesis.strategies import tuples
55 from six import assertRaisesRegex
56 from six import binary_type
57 from six import byte2int
58 from six import indexbytes
59 from six import int2byte
60 from six import iterbytes
62 from six import text_type
63 from six import unichr as six_unichr
64 from six.moves import xrange as six_xrange
65 from six.moves.cPickle import dumps as pickle_dumps
66 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
67 from six.moves.cPickle import loads as pickle_loads
69 from pyderasn import _pp
70 from pyderasn import abs_decode_path
71 from pyderasn import Any
72 from pyderasn import BitString
73 from pyderasn import BMPString
74 from pyderasn import Boolean
75 from pyderasn import BoundsError
76 from pyderasn import Choice
77 from pyderasn import DecodeError
78 from pyderasn import DecodePathDefBy
79 from pyderasn import encode2pass
80 from pyderasn import encode_cer
81 from pyderasn import Enumerated
82 from pyderasn import EOC
83 from pyderasn import EOC_LEN
84 from pyderasn import ExceedingData
85 from pyderasn import GeneralizedTime
86 from pyderasn import GeneralString
87 from pyderasn import GraphicString
88 from pyderasn import hexdec
89 from pyderasn import hexenc
90 from pyderasn import IA5String
91 from pyderasn import Integer
92 from pyderasn import InvalidLength
93 from pyderasn import InvalidOID
94 from pyderasn import InvalidValueType
95 from pyderasn import len_decode
96 from pyderasn import len_encode
97 from pyderasn import LEN_YYMMDDHHMMSSZ
98 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
99 from pyderasn import LEN_YYYYMMDDHHMMSSZ
100 from pyderasn import LENINDEF
101 from pyderasn import LenIndefForm
102 from pyderasn import NotEnoughData
103 from pyderasn import Null
104 from pyderasn import NumericString
105 from pyderasn import ObjectIdentifier
106 from pyderasn import ObjNotReady
107 from pyderasn import ObjUnknown
108 from pyderasn import OctetString
109 from pyderasn import pp_console_row
110 from pyderasn import pprint
111 from pyderasn import PrintableString
112 from pyderasn import Sequence
113 from pyderasn import SequenceOf
114 from pyderasn import Set
115 from pyderasn import SetOf
116 from pyderasn import tag_ctxc
117 from pyderasn import tag_ctxp
118 from pyderasn import tag_decode
119 from pyderasn import tag_encode
120 from pyderasn import tag_strip
121 from pyderasn import TagClassApplication
122 from pyderasn import TagClassContext
123 from pyderasn import TagClassPrivate
124 from pyderasn import TagClassUniversal
125 from pyderasn import TagFormConstructed
126 from pyderasn import TagFormPrimitive
127 from pyderasn import TagMismatch
128 from pyderasn import TeletexString
129 from pyderasn import UniversalString
130 from pyderasn import UTCTime
131 from pyderasn import UTF8String
132 from pyderasn import VideotexString
133 from pyderasn import VisibleString
136 max_examples = environ.get("MAX_EXAMPLES")
137 settings.register_profile("local", settings(
139 **({"max_examples": int(max_examples)} if max_examples else {})
141 settings.load_profile("local")
142 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
144 tag_classes = sampled_from((
150 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
151 decode_path_strat = lists(integers(), max_size=3).map(
152 lambda decode_path: tuple(str(dp) for dp in decode_path)
154 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
157 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
159 self_module = import_module(__name__)
162 def register_class(klass):
163 klassname = klass.__name__ + str(time()).replace(".", "")
164 klass.__name__ = klassname
165 klass.__qualname__ = klassname
166 setattr(self_module, klassname, klass)
169 def assert_exceeding_data(self, call, junk):
172 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
177 class TestHex(TestCase):
179 def test_symmetric(self, data):
180 self.assertEqual(hexdec(hexenc(data)), data)
183 class TestTagCoder(TestCase):
184 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
188 integers(min_value=0, max_value=30),
191 def test_short(self, klass, form, num, junk):
192 raw = tag_encode(klass=klass, form=form, num=num)
193 self.assertEqual(tag_decode(raw), (klass, form, num))
194 self.assertEqual(len(raw), 1)
196 byte2int(tag_encode(klass=klass, form=form, num=0)),
197 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
199 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
200 self.assertSequenceEqual(stripped.tobytes(), raw)
201 self.assertEqual(tlen, len(raw))
202 self.assertSequenceEqual(tail, junk)
204 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
208 integers(min_value=31),
211 def test_long(self, klass, form, num, junk):
212 raw = tag_encode(klass=klass, form=form, num=num)
213 self.assertEqual(tag_decode(raw), (klass, form, num))
214 self.assertGreater(len(raw), 1)
216 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
219 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
220 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
221 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
222 self.assertSequenceEqual(stripped.tobytes(), raw)
223 self.assertEqual(tlen, len(raw))
224 self.assertSequenceEqual(tail, junk)
226 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
227 @given(integers(min_value=31))
228 def test_unfinished_tag(self, num):
229 raw = bytearray(tag_encode(num=num))
230 for i in range(1, len(raw)):
232 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
233 tag_strip(bytes(raw))
235 def test_go_vectors_valid(self):
236 for data, (eklass, etag, elen, eform) in (
237 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
238 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
239 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
240 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
241 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
242 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
243 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
244 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
245 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
246 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
248 tag, _, len_encoded = tag_strip(memoryview(data))
249 klass, form, num = tag_decode(tag)
250 _len, _, tail = len_decode(len_encoded)
251 self.assertSequenceEqual(tail, b"")
252 self.assertEqual(klass, eklass)
253 self.assertEqual(num, etag)
254 self.assertEqual(_len, elen)
255 self.assertEqual(form, eform)
257 def test_go_vectors_invalid(self):
265 with self.assertRaises(DecodeError):
266 _, _, len_encoded = tag_strip(memoryview(data))
267 len_decode(len_encoded)
270 integers(min_value=0, max_value=127),
271 integers(min_value=0, max_value=2),
273 def test_long_instead_of_short(self, l, dummy_num):
274 octets = (b"\x00" * dummy_num) + int2byte(l)
275 octets = int2byte((dummy_num + 1) | 0x80) + octets
276 with self.assertRaises(DecodeError):
280 class TestLenCoder(TestCase):
281 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
283 integers(min_value=0, max_value=127),
286 def test_short(self, l, junk):
287 raw = len_encode(l) + junk
288 decoded, llen, tail = len_decode(memoryview(raw))
289 self.assertEqual(decoded, l)
290 self.assertEqual(llen, 1)
291 self.assertEqual(len(raw), 1 + len(junk))
292 self.assertEqual(tail.tobytes(), junk)
294 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
296 integers(min_value=128),
299 def test_long(self, l, junk):
300 raw = len_encode(l) + junk
301 decoded, llen, tail = len_decode(memoryview(raw))
302 self.assertEqual(decoded, l)
303 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
304 self.assertEqual(llen, len(raw) - len(junk))
305 self.assertNotEqual(indexbytes(raw, 1), 0)
306 self.assertSequenceEqual(tail.tobytes(), junk)
308 def test_empty(self):
309 with self.assertRaises(NotEnoughData):
312 @given(integers(min_value=128))
313 def test_stripped(self, _len):
314 with self.assertRaises(NotEnoughData):
315 len_decode(len_encode(_len)[:-1])
318 text_printable = text(alphabet=printable, min_size=1)
322 def text_letters(draw):
323 result = draw(text(alphabet=ascii_letters, min_size=1))
325 result = result.encode("ascii")
329 class CommonMixin(object):
330 def test_tag_default(self):
331 obj = self.base_klass()
332 self.assertEqual(obj.tag, obj.tag_default)
334 def test_simultaneous_impl_expl(self):
335 with self.assertRaises(ValueError):
336 self.base_klass(impl=b"whatever", expl=b"whenever")
338 @given(binary(min_size=1), integers(), integers(), integers())
339 def test_decoded(self, impl, offset, llen, vlen):
340 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
341 self.assertEqual(obj.offset, offset)
342 self.assertEqual(obj.llen, llen)
343 self.assertEqual(obj.vlen, vlen)
344 self.assertEqual(obj.tlen, len(impl))
345 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
347 @given(binary(min_size=1))
348 def test_impl_inherited(self, impl_tag):
349 class Inherited(self.base_klass):
352 self.assertSequenceEqual(obj.impl, impl_tag)
353 self.assertFalse(obj.expled)
355 tag_class, _, tag_num = tag_decode(impl_tag)
356 self.assertEqual(obj.tag_order, (tag_class, tag_num))
358 @given(binary(min_size=1))
359 def test_expl_inherited(self, expl_tag):
360 class Inherited(self.base_klass):
363 self.assertSequenceEqual(obj.expl, expl_tag)
364 self.assertTrue(obj.expled)
366 tag_class, _, tag_num = tag_decode(expl_tag)
367 self.assertEqual(obj.tag_order, (tag_class, tag_num))
369 def assert_copied_basic_fields(self, obj, obj_copied):
370 self.assertEqual(obj, obj_copied)
371 self.assertSequenceEqual(obj.tag, obj_copied.tag)
372 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
373 self.assertEqual(obj.default, obj_copied.default)
374 self.assertEqual(obj.optional, obj_copied.optional)
375 self.assertEqual(obj.offset, obj_copied.offset)
376 self.assertEqual(obj.llen, obj_copied.llen)
377 self.assertEqual(obj.vlen, obj_copied.vlen)
379 self.assertEqual(obj.tag_order, obj_copied.tag_order)
383 def boolean_values_strategy(draw, do_expl=False):
384 value = draw(one_of(none(), booleans()))
388 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
390 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
391 default = draw(one_of(none(), booleans()))
392 optional = draw(one_of(none(), booleans()))
394 draw(integers(min_value=0)),
395 draw(integers(min_value=0)),
396 draw(integers(min_value=0)),
398 return (value, impl, expl, default, optional, _decoded)
401 class BooleanInherited(Boolean):
405 class TestBoolean(CommonMixin, TestCase):
408 def test_invalid_value_type(self):
409 with self.assertRaises(InvalidValueType) as err:
414 def test_optional(self, optional):
415 obj = Boolean(default=Boolean(False), optional=optional)
416 self.assertTrue(obj.optional)
419 def test_ready(self, value):
421 self.assertFalse(obj.ready)
424 pprint(obj, big_blobs=True, with_decode_path=True)
425 with self.assertRaises(ObjNotReady) as err:
427 with self.assertRaises(ObjNotReady) as err:
431 self.assertTrue(obj.ready)
434 pprint(obj, big_blobs=True, with_decode_path=True)
436 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
437 def test_comparison(self, value1, value2, tag1, tag2):
438 for klass in (Boolean, BooleanInherited):
441 self.assertEqual(obj1 == obj2, value1 == value2)
442 self.assertEqual(obj1 != obj2, value1 != value2)
443 self.assertEqual(obj1 == bool(obj2), value1 == value2)
444 obj1 = klass(value1, impl=tag1)
445 obj2 = klass(value1, impl=tag2)
446 self.assertEqual(obj1 == obj2, tag1 == tag2)
447 self.assertEqual(obj1 != obj2, tag1 != tag2)
449 @given(data_strategy())
450 def test_call(self, d):
451 for klass in (Boolean, BooleanInherited):
459 ) = d.draw(boolean_values_strategy())
465 optional_initial or False,
475 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
476 obj = obj_initial(value, impl, expl, default, optional)
478 value_expected = default if value is None else value
480 default_initial if value_expected is None
483 self.assertEqual(obj, value_expected)
484 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
485 self.assertEqual(obj.expl_tag, expl or expl_initial)
488 default_initial if default is None else default,
490 if obj.default is None:
491 optional = optional_initial if optional is None else optional
492 optional = False if optional is None else optional
495 self.assertEqual(obj.optional, optional)
497 @given(boolean_values_strategy())
498 def test_copy(self, values):
499 for klass in (Boolean, BooleanInherited):
501 for copy_func in copy_funcs:
502 obj_copied = copy_func(obj)
503 self.assert_copied_basic_fields(obj, obj_copied)
507 integers(min_value=1).map(tag_encode),
509 def test_stripped(self, value, tag_impl):
510 obj = Boolean(value, impl=tag_impl)
511 with self.assertRaises(NotEnoughData):
512 obj.decode(obj.encode()[:-1])
513 with self.assertRaises(NotEnoughData):
514 obj.decode(encode2pass(obj)[:-1])
518 integers(min_value=1).map(tag_ctxc),
520 def test_stripped_expl(self, value, tag_expl):
521 obj = Boolean(value, expl=tag_expl)
522 with self.assertRaises(NotEnoughData):
523 obj.decode(obj.encode()[:-1])
524 with self.assertRaises(NotEnoughData):
525 obj.decode(encode2pass(obj)[:-1])
528 integers(min_value=31),
529 integers(min_value=0),
532 def test_bad_tag(self, tag, offset, decode_path):
533 with self.assertRaises(DecodeError) as err:
535 tag_encode(tag)[:-1],
537 decode_path=decode_path,
540 self.assertEqual(err.exception.offset, offset)
541 self.assertEqual(err.exception.decode_path, decode_path)
544 integers(min_value=31),
545 integers(min_value=0),
548 def test_bad_expl_tag(self, tag, offset, decode_path):
549 with self.assertRaises(DecodeError) as err:
550 Boolean(expl=Boolean.tag_default).decode(
551 tag_encode(tag)[:-1],
553 decode_path=decode_path,
556 self.assertEqual(err.exception.offset, offset)
557 self.assertEqual(err.exception.decode_path, decode_path)
560 integers(min_value=128),
561 integers(min_value=0),
564 def test_bad_len(self, l, offset, decode_path):
565 with self.assertRaises(DecodeError) as err:
567 Boolean.tag_default + len_encode(l)[:-1],
569 decode_path=decode_path,
572 self.assertEqual(err.exception.offset, offset)
573 self.assertEqual(err.exception.decode_path, decode_path)
576 integers(min_value=128),
577 integers(min_value=0),
580 def test_bad_expl_len(self, l, offset, decode_path):
581 with self.assertRaises(DecodeError) as err:
582 Boolean(expl=Boolean.tag_default).decode(
583 Boolean.tag_default + len_encode(l)[:-1],
585 decode_path=decode_path,
588 self.assertEqual(err.exception.offset, offset)
589 self.assertEqual(err.exception.decode_path, decode_path)
591 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
593 boolean_values_strategy(),
595 integers(min_value=1).map(tag_ctxc),
596 integers(min_value=0),
600 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
601 for klass in (Boolean, BooleanInherited):
602 _, _, _, default, optional, _decoded = values
611 pprint(obj, big_blobs=True, with_decode_path=True)
612 self.assertFalse(obj.expled)
613 obj_encoded = obj.encode()
614 self.assertEqual(encode2pass(obj), obj_encoded)
615 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
616 obj_expled = obj(value, expl=tag_expl)
617 self.assertTrue(obj_expled.expled)
619 list(obj_expled.pps())
620 pprint(obj_expled, big_blobs=True, with_decode_path=True)
621 obj_expled_cer = encode_cer(obj_expled)
622 self.assertNotEqual(obj_expled_cer, obj_encoded)
623 self.assertSequenceEqual(
624 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
627 obj_expled_hex_encoded = obj_expled.hexencode()
628 ctx_copied = deepcopy(ctx_dummy)
629 obj_decoded, tail = obj_expled.hexdecode(
630 obj_expled_hex_encoded + hexenc(tail_junk),
634 self.assertDictEqual(ctx_copied, ctx_dummy)
636 list(obj_decoded.pps())
637 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
638 self.assertEqual(tail, tail_junk)
639 self.assertEqual(obj_decoded, obj_expled)
640 self.assertNotEqual(obj_decoded, obj)
641 self.assertEqual(bool(obj_decoded), bool(obj_expled))
642 self.assertEqual(bool(obj_decoded), bool(obj))
643 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
644 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
645 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
647 obj_decoded.expl_llen,
648 len(len_encode(len(obj_encoded))),
650 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
651 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
654 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
656 self.assertEqual(obj_decoded.expl_offset, offset)
657 assert_exceeding_data(
659 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
663 evgens = list(obj_expled.decode_evgen(
664 hexdec(obj_expled_hex_encoded) + tail_junk,
666 decode_path=decode_path,
669 self.assertEqual(len(evgens), 1)
670 _decode_path, obj, tail = evgens[0]
671 self.assertSequenceEqual(tail, tail_junk)
672 self.assertEqual(_decode_path, decode_path)
673 self.assertEqual(obj, obj_decoded)
674 self.assertEqual(obj.expl_offset, offset)
678 @given(integers(min_value=2))
679 def test_invalid_len(self, l):
680 with self.assertRaises(InvalidLength):
681 Boolean().decode(b"".join((
687 @given(integers(min_value=0 + 1, max_value=255 - 1))
688 def test_ber_value(self, value):
689 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
690 Boolean().decode(b"".join((
700 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
701 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
702 self.assertTrue(bool(obj))
703 self.assertTrue(obj.ber_encoded)
704 self.assertFalse(obj.lenindef)
705 self.assertTrue(obj.bered)
707 self.assertTrue(obj.ber_encoded)
708 self.assertFalse(obj.lenindef)
709 self.assertTrue(obj.bered)
712 integers(min_value=1).map(tag_ctxc),
713 binary().filter(lambda x: not x.startswith(EOC)),
715 def test_ber_expl_no_eoc(self, expl, junk):
716 encoded = expl + LENINDEF + Boolean(False).encode()
717 with self.assertRaises(LenIndefForm):
718 Boolean(expl=expl).decode(encoded + junk)
719 with assertRaisesRegex(self, DecodeError, "no EOC"):
720 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
721 obj, tail = Boolean(expl=expl).decode(
722 encoded + EOC + junk,
725 self.assertTrue(obj.expl_lenindef)
726 self.assertFalse(obj.lenindef)
727 self.assertFalse(obj.ber_encoded)
728 self.assertTrue(obj.bered)
730 self.assertTrue(obj.expl_lenindef)
731 self.assertFalse(obj.lenindef)
732 self.assertFalse(obj.ber_encoded)
733 self.assertTrue(obj.bered)
734 self.assertSequenceEqual(tail, junk)
737 pprint(obj, big_blobs=True, with_decode_path=True)
740 integers(min_value=1).map(tag_ctxc),
747 def test_ber_expl(self, expl, values):
753 Boolean(value).encode() +
756 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
758 class SeqOf(SequenceOf):
759 schema = Boolean(expl=expl)
760 with self.assertRaises(LenIndefForm):
761 SeqOf().decode(encoded)
762 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
763 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
764 self.assertSequenceEqual(tail, b"")
765 self.assertSequenceEqual([bool(v) for v in seqof], values)
781 len(expl) + 1 + 3 + EOC_LEN,
792 pprint(seqof, big_blobs=True, with_decode_path=True)
796 def integer_values_strategy(draw, do_expl=False):
797 bound_min, value, default, bound_max = sorted(draw(sets(
806 _specs = draw(sets(text_letters()))
809 min_size=len(_specs),
810 max_size=len(_specs),
812 _specs = list(zip(_specs, values))
815 bounds = (bound_min, bound_max)
819 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
821 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
824 optional = draw(one_of(none(), booleans()))
826 draw(integers(min_value=0)),
827 draw(integers(min_value=0)),
828 draw(integers(min_value=0)),
830 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
833 class IntegerInherited(Integer):
837 class TestInteger(CommonMixin, TestCase):
840 def test_invalid_value_type(self):
841 with self.assertRaises(InvalidValueType) as err:
845 @given(sets(text_letters(), min_size=2))
846 def test_unknown_name(self, names_input):
847 missing = names_input.pop()
850 schema = [(n, 123) for n in names_input]
851 with self.assertRaises(ObjUnknown) as err:
855 @given(sets(text_letters(), min_size=2))
856 def test_known_name(self, names_input):
858 schema = [(n, 123) for n in names_input]
859 Int(names_input.pop())
862 def test_optional(self, optional):
863 obj = Integer(default=Integer(0), optional=optional)
864 self.assertTrue(obj.optional)
867 def test_ready(self, value):
869 self.assertFalse(obj.ready)
872 pprint(obj, big_blobs=True, with_decode_path=True)
873 with self.assertRaises(ObjNotReady) as err:
875 with self.assertRaises(ObjNotReady) as err:
879 self.assertTrue(obj.ready)
882 pprint(obj, big_blobs=True, with_decode_path=True)
885 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
886 def test_comparison(self, value1, value2, tag1, tag2):
887 for klass in (Integer, IntegerInherited):
890 self.assertEqual(obj1 == obj2, value1 == value2)
891 self.assertEqual(obj1 != obj2, value1 != value2)
892 self.assertEqual(obj1 == int(obj2), value1 == value2)
893 obj1 = klass(value1, impl=tag1)
894 obj2 = klass(value1, impl=tag2)
895 self.assertEqual(obj1 == obj2, tag1 == tag2)
896 self.assertEqual(obj1 != obj2, tag1 != tag2)
898 @given(lists(integers()))
899 def test_sorted_works(self, values):
900 self.assertSequenceEqual(
901 [int(v) for v in sorted(Integer(v) for v in values)],
905 @given(data_strategy())
906 def test_named(self, d):
907 names_input = list(d.draw(sets(text_letters(), min_size=1)))
908 values_input = list(d.draw(sets(
910 min_size=len(names_input),
911 max_size=len(names_input),
913 chosen_name = d.draw(sampled_from(names_input))
914 names_input = dict(zip(names_input, values_input))
918 _int = Int(chosen_name)
919 self.assertEqual(_int.named, chosen_name)
920 self.assertEqual(int(_int), names_input[chosen_name])
922 @given(integers(), integers(min_value=0), integers(min_value=0))
923 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
924 value = bound_min + value_delta
925 bound_max = value + bound_delta
926 Integer(value=value, bounds=(bound_min, bound_max))
928 @given(sets(integers(), min_size=3, max_size=3))
929 def test_bounds_unsatisfied(self, values):
930 values = sorted(values)
931 with self.assertRaises(BoundsError) as err:
932 Integer(value=values[0], bounds=(values[1], values[2]))
934 with assertRaisesRegex(self, DecodeError, "bounds") as err:
935 Integer(bounds=(values[1], values[2])).decode(
936 Integer(values[0]).encode()
939 with assertRaisesRegex(self, DecodeError, "bounds") as err:
940 Integer(bounds=(values[1], values[2])).decode(
941 encode2pass(Integer(values[0]))
943 with self.assertRaises(BoundsError) as err:
944 Integer(value=values[2], bounds=(values[0], values[1]))
946 with assertRaisesRegex(self, DecodeError, "bounds") as err:
947 Integer(bounds=(values[0], values[1])).decode(
948 Integer(values[2]).encode()
951 with assertRaisesRegex(self, DecodeError, "bounds") as err:
952 Integer(bounds=(values[0], values[1])).decode(
953 encode2pass(Integer(values[2]))
956 @given(data_strategy())
957 def test_call(self, d):
958 for klass in (Integer, IntegerInherited):
968 ) = d.draw(integer_values_strategy())
975 optional_initial or False,
988 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
989 if (default is None) and (obj_initial.default is not None):
993 (value is not None) and
994 (bounds_initial is not None) and
995 not (bounds_initial[0] <= value <= bounds_initial[1])
1000 (default is not None) and
1001 (bounds_initial is not None) and
1002 not (bounds_initial[0] <= default <= bounds_initial[1])
1005 obj = obj_initial(value, bounds, impl, expl, default, optional)
1007 value_expected = default if value is None else value
1009 default_initial if value_expected is None
1012 self.assertEqual(obj, value_expected)
1013 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1014 self.assertEqual(obj.expl_tag, expl or expl_initial)
1017 default_initial if default is None else default,
1019 if obj.default is None:
1020 optional = optional_initial if optional is None else optional
1021 optional = False if optional is None else optional
1024 self.assertEqual(obj.optional, optional)
1026 (obj._bound_min, obj._bound_max),
1027 bounds or bounds_initial or (float("-inf"), float("+inf")),
1031 {} if _specs_initial is None else dict(_specs_initial),
1034 @given(integer_values_strategy())
1035 def test_copy(self, values):
1036 for klass in (Integer, IntegerInherited):
1037 obj = klass(*values)
1038 for copy_func in copy_funcs:
1039 obj_copied = copy_func(obj)
1040 self.assert_copied_basic_fields(obj, obj_copied)
1041 self.assertEqual(obj.specs, obj_copied.specs)
1042 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1043 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1044 self.assertEqual(obj._value, obj_copied._value)
1048 integers(min_value=1).map(tag_encode),
1050 def test_stripped(self, value, tag_impl):
1051 obj = Integer(value, impl=tag_impl)
1052 with self.assertRaises(NotEnoughData):
1053 obj.decode(obj.encode()[:-1])
1057 integers(min_value=1).map(tag_ctxc),
1059 def test_stripped_expl(self, value, tag_expl):
1060 obj = Integer(value, expl=tag_expl)
1061 with self.assertRaises(NotEnoughData):
1062 obj.decode(obj.encode()[:-1])
1064 def test_zero_len(self):
1065 with self.assertRaises(NotEnoughData):
1066 Integer().decode(b"".join((
1067 Integer.tag_default,
1072 integers(min_value=31),
1073 integers(min_value=0),
1076 def test_bad_tag(self, tag, offset, decode_path):
1077 with self.assertRaises(DecodeError) as err:
1079 tag_encode(tag)[:-1],
1081 decode_path=decode_path,
1084 self.assertEqual(err.exception.offset, offset)
1085 self.assertEqual(err.exception.decode_path, decode_path)
1088 integers(min_value=128),
1089 integers(min_value=0),
1092 def test_bad_len(self, l, offset, decode_path):
1093 with self.assertRaises(DecodeError) as err:
1095 Integer.tag_default + len_encode(l)[:-1],
1097 decode_path=decode_path,
1100 self.assertEqual(err.exception.offset, offset)
1101 self.assertEqual(err.exception.decode_path, decode_path)
1104 sets(integers(), min_size=2, max_size=2),
1105 integers(min_value=0),
1108 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1109 value, bound_min = list(sorted(ints))
1112 bounds = (bound_min, bound_min)
1113 with self.assertRaises(DecodeError) as err:
1115 Integer(value).encode(),
1117 decode_path=decode_path,
1120 self.assertEqual(err.exception.offset, offset)
1121 self.assertEqual(err.exception.decode_path, decode_path)
1123 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1125 integer_values_strategy(),
1127 integers(min_value=1).map(tag_ctxc),
1128 integers(min_value=0),
1132 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1133 for klass in (Integer, IntegerInherited):
1134 _, _, _, _, default, optional, _, _decoded = values
1143 pprint(obj, big_blobs=True, with_decode_path=True)
1144 self.assertFalse(obj.expled)
1145 obj_encoded = obj.encode()
1146 self.assertEqual(encode2pass(obj), obj_encoded)
1147 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1148 obj_expled = obj(value, expl=tag_expl)
1149 self.assertTrue(obj_expled.expled)
1151 list(obj_expled.pps())
1152 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1153 obj_expled_encoded = obj_expled.encode()
1154 obj_expled_cer = encode_cer(obj_expled)
1155 self.assertNotEqual(obj_expled_cer, obj_encoded)
1156 self.assertSequenceEqual(
1157 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1160 ctx_copied = deepcopy(ctx_dummy)
1161 obj_decoded, tail = obj_expled.decode(
1162 obj_expled_encoded + tail_junk,
1166 self.assertDictEqual(ctx_copied, ctx_dummy)
1168 list(obj_decoded.pps())
1169 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1170 self.assertEqual(tail, tail_junk)
1171 self.assertEqual(obj_decoded, obj_expled)
1172 self.assertNotEqual(obj_decoded, obj)
1173 self.assertEqual(int(obj_decoded), int(obj_expled))
1174 self.assertEqual(int(obj_decoded), int(obj))
1175 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1176 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1177 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1179 obj_decoded.expl_llen,
1180 len(len_encode(len(obj_encoded))),
1182 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1183 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1186 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1188 self.assertEqual(obj_decoded.expl_offset, offset)
1189 assert_exceeding_data(
1191 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1195 evgens = list(obj_expled.decode_evgen(
1196 obj_expled_encoded + tail_junk,
1198 decode_path=decode_path,
1201 self.assertEqual(len(evgens), 1)
1202 _decode_path, obj, tail = evgens[0]
1203 self.assertSequenceEqual(tail, tail_junk)
1204 self.assertEqual(_decode_path, decode_path)
1205 self.assertEqual(obj, obj_decoded)
1206 self.assertEqual(obj.expl_offset, offset)
1210 def test_go_vectors_valid(self):
1211 for data, expect in ((
1215 (b"\xff\x7f", -129),
1219 (b"\xff\x00", -256),
1223 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1224 (b"\x80\x00\x00\x00", -2147483648),
1227 Integer().decode(b"".join((
1228 Integer.tag_default,
1229 len_encode(len(data)),
1235 def test_go_vectors_invalid(self):
1240 with self.assertRaises(DecodeError):
1241 Integer().decode(b"".join((
1242 Integer.tag_default,
1243 len_encode(len(data)),
1249 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1252 if draw(booleans()):
1253 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1255 integers(min_value=0, max_value=255),
1256 min_size=len(schema),
1257 max_size=len(schema),
1259 schema = list(zip(schema, bits))
1261 def _value(value_required):
1262 if not value_required and draw(booleans()):
1264 generation_choice = 0
1266 generation_choice = draw(sampled_from((1, 2, 3)))
1267 if generation_choice == 1 or draw(booleans()):
1268 return "'%s'B" % "".join(draw(lists(
1269 sampled_from(("0", "1")),
1270 max_size=len(schema),
1272 if generation_choice == 2 or draw(booleans()):
1273 return draw(binary(max_size=len(schema) // 8))
1274 if generation_choice == 3 or draw(booleans()):
1275 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1277 value = _value(value_required)
1278 default = _value(value_required=False)
1282 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1284 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1285 optional = draw(one_of(none(), booleans()))
1287 draw(integers(min_value=0)),
1288 draw(integers(min_value=0)),
1289 draw(integers(min_value=0)),
1291 return (schema, value, impl, expl, default, optional, _decoded)
1294 class BitStringInherited(BitString):
1298 class TestBitString(CommonMixin, TestCase):
1299 base_klass = BitString
1301 @given(lists(booleans()))
1302 def test_b_encoding(self, bits):
1303 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1304 self.assertEqual(obj.bit_len, len(bits))
1305 self.assertSequenceEqual(list(obj), bits)
1306 for i, bit in enumerate(bits):
1307 self.assertEqual(obj[i], bit)
1309 @given(lists(booleans()))
1310 def test_out_of_bounds_bits(self, bits):
1311 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1312 for i in range(len(bits), len(bits) * 2):
1313 self.assertFalse(obj[i])
1315 def test_bad_b_encoding(self):
1316 with self.assertRaises(ValueError):
1317 BitString("'010120101'B")
1320 integers(min_value=1, max_value=255),
1321 integers(min_value=1, max_value=255),
1323 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1324 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1325 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1326 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1328 class BS(BitString):
1329 schema = (("whatever", 0),)
1330 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1331 self.assertEqual(obj.bit_len, leading_zeros + 1)
1332 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1334 def test_zero_len(self):
1335 with self.assertRaises(NotEnoughData):
1336 BitString().decode(b"".join((
1337 BitString.tag_default,
1341 def test_invalid_value_type(self):
1342 with self.assertRaises(InvalidValueType) as err:
1345 with self.assertRaises(InvalidValueType) as err:
1349 def test_obj_unknown(self):
1350 with self.assertRaises(ObjUnknown) as err:
1351 BitString(b"whatever")["whenever"]
1354 def test_get_invalid_type(self):
1355 with self.assertRaises(InvalidValueType) as err:
1356 BitString(b"whatever")[(1, 2, 3)]
1359 @given(data_strategy())
1360 def test_unknown_name(self, d):
1361 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1362 missing = _schema.pop()
1364 class BS(BitString):
1365 schema = [(n, i) for i, n in enumerate(_schema)]
1366 with self.assertRaises(ObjUnknown) as err:
1371 def test_optional(self, optional):
1372 obj = BitString(default=BitString(b""), optional=optional)
1373 self.assertTrue(obj.optional)
1376 def test_ready(self, value):
1378 self.assertFalse(obj.ready)
1381 pprint(obj, big_blobs=True, with_decode_path=True)
1382 with self.assertRaises(ObjNotReady) as err:
1385 with self.assertRaises(ObjNotReady) as err:
1387 obj = BitString(value)
1388 self.assertTrue(obj.ready)
1391 pprint(obj, big_blobs=True, with_decode_path=True)
1394 tuples(integers(min_value=0), binary()),
1395 tuples(integers(min_value=0), binary()),
1399 def test_comparison(self, value1, value2, tag1, tag2):
1400 for klass in (BitString, BitStringInherited):
1401 obj1 = klass(value1)
1402 obj2 = klass(value2)
1403 self.assertEqual(obj1 == obj2, value1 == value2)
1404 self.assertEqual(obj1 != obj2, value1 != value2)
1405 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1406 obj1 = klass(value1, impl=tag1)
1407 obj2 = klass(value1, impl=tag2)
1408 self.assertEqual(obj1 == obj2, tag1 == tag2)
1409 self.assertEqual(obj1 != obj2, tag1 != tag2)
1411 @given(data_strategy())
1412 def test_call(self, d):
1413 for klass in (BitString, BitStringInherited):
1422 ) = d.draw(bit_string_values_strategy())
1425 schema = schema_initial
1427 value=value_initial,
1430 default=default_initial,
1431 optional=optional_initial or False,
1432 _decoded=_decoded_initial,
1442 ) = d.draw(bit_string_values_strategy(
1443 schema=schema_initial,
1444 do_expl=impl_initial is None,
1453 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1454 self.assertEqual(obj.expl_tag, expl or expl_initial)
1455 if obj.default is None:
1456 optional = optional_initial if optional is None else optional
1457 optional = False if optional is None else optional
1460 self.assertEqual(obj.optional, optional)
1461 self.assertEqual(obj.specs, obj_initial.specs)
1463 @given(bit_string_values_strategy())
1464 def test_copy(self, values):
1465 for klass in (BitString, BitStringInherited):
1466 _schema, value, impl, expl, default, optional, _decoded = values
1476 optional=optional or False,
1479 for copy_func in copy_funcs:
1480 obj_copied = copy_func(obj)
1481 self.assert_copied_basic_fields(obj, obj_copied)
1482 self.assertEqual(obj.specs, obj_copied.specs)
1483 self.assertEqual(obj._value, obj_copied._value)
1487 integers(min_value=1).map(tag_encode),
1489 def test_stripped(self, value, tag_impl):
1490 obj = BitString(value, impl=tag_impl)
1491 with self.assertRaises(NotEnoughData):
1492 obj.decode(obj.encode()[:-1])
1496 integers(min_value=1).map(tag_ctxc),
1498 def test_stripped_expl(self, value, tag_expl):
1499 obj = BitString(value, expl=tag_expl)
1500 with self.assertRaises(NotEnoughData):
1501 obj.decode(obj.encode()[:-1])
1504 integers(min_value=31),
1505 integers(min_value=0),
1508 def test_bad_tag(self, tag, offset, decode_path):
1509 with self.assertRaises(DecodeError) as err:
1511 tag_encode(tag)[:-1],
1513 decode_path=decode_path,
1516 self.assertEqual(err.exception.offset, offset)
1517 self.assertEqual(err.exception.decode_path, decode_path)
1520 integers(min_value=128),
1521 integers(min_value=0),
1524 def test_bad_len(self, l, offset, decode_path):
1525 with self.assertRaises(DecodeError) as err:
1527 BitString.tag_default + len_encode(l)[:-1],
1529 decode_path=decode_path,
1532 self.assertEqual(err.exception.offset, offset)
1533 self.assertEqual(err.exception.decode_path, decode_path)
1535 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1536 @given(data_strategy())
1537 def test_symmetric(self, d):
1546 ) = d.draw(bit_string_values_strategy(value_required=True))
1547 tail_junk = d.draw(binary(max_size=5))
1548 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1549 offset = d.draw(integers(min_value=0))
1550 decode_path = d.draw(decode_path_strat)
1551 for klass in (BitString, BitStringInherited):
1562 pprint(obj, big_blobs=True, with_decode_path=True)
1563 self.assertFalse(obj.expled)
1564 obj_encoded = obj.encode()
1565 self.assertEqual(encode2pass(obj), obj_encoded)
1566 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1567 obj_expled = obj(value, expl=tag_expl)
1568 self.assertTrue(obj_expled.expled)
1570 list(obj_expled.pps())
1571 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1572 obj_expled_encoded = obj_expled.encode()
1573 obj_expled_cer = encode_cer(obj_expled)
1574 self.assertNotEqual(obj_expled_cer, obj_encoded)
1575 self.assertSequenceEqual(
1576 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1579 ctx_copied = deepcopy(ctx_dummy)
1580 obj_decoded, tail = obj_expled.decode(
1581 obj_expled_encoded + tail_junk,
1585 self.assertDictEqual(ctx_copied, ctx_dummy)
1587 list(obj_decoded.pps())
1588 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1589 self.assertEqual(tail, tail_junk)
1590 self.assertEqual(obj_decoded, obj_expled)
1591 self.assertNotEqual(obj_decoded, obj)
1592 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1593 self.assertEqual(bytes(obj_decoded), bytes(obj))
1594 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1595 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1596 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1598 obj_decoded.expl_llen,
1599 len(len_encode(len(obj_encoded))),
1601 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1602 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1605 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1607 self.assertEqual(obj_decoded.expl_offset, offset)
1608 if isinstance(value, tuple):
1609 self.assertSetEqual(set(value), set(obj_decoded.named))
1612 assert_exceeding_data(
1614 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1618 evgens = list(obj_expled.decode_evgen(
1619 obj_expled_encoded + tail_junk,
1621 decode_path=decode_path,
1624 self.assertEqual(len(evgens), 1)
1625 _decode_path, obj, tail = evgens[0]
1626 self.assertSequenceEqual(tail, tail_junk)
1627 self.assertEqual(_decode_path, decode_path)
1628 self.assertEqual(obj.expl_offset, offset)
1632 @given(integers(min_value=1, max_value=255))
1633 def test_bad_zero_value(self, pad_size):
1634 with self.assertRaises(DecodeError):
1635 BitString().decode(b"".join((
1636 BitString.tag_default,
1641 def test_go_vectors_invalid(self):
1647 with self.assertRaises(DecodeError):
1648 BitString().decode(b"".join((
1649 BitString.tag_default,
1654 def test_go_vectors_valid(self):
1655 obj, _ = BitString().decode(b"".join((
1656 BitString.tag_default,
1660 self.assertEqual(bytes(obj), b"")
1661 self.assertEqual(obj.bit_len, 0)
1663 obj, _ = BitString().decode(b"".join((
1664 BitString.tag_default,
1668 self.assertEqual(bytes(obj), b"\x00")
1669 self.assertEqual(obj.bit_len, 1)
1671 obj = BitString((16, b"\x82\x40"))
1672 self.assertTrue(obj[0])
1673 self.assertFalse(obj[1])
1674 self.assertTrue(obj[6])
1675 self.assertTrue(obj[9])
1676 self.assertFalse(obj[17])
1678 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1680 integers(min_value=1, max_value=30),
1683 binary(min_size=1, max_size=5),
1685 binary(min_size=1, max_size=5),
1693 lists(booleans(), min_size=1),
1697 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1698 def chunk_constructed(contents):
1700 tag_encode(form=TagFormConstructed, num=3) +
1702 b"".join(BitString(content).encode() for content in contents) +
1706 chunks_len_expected = []
1707 payload_expected = b""
1708 bit_len_expected = 0
1709 for chunk_input in chunk_inputs:
1710 if isinstance(chunk_input, binary_type):
1711 chunks.append(BitString(chunk_input).encode())
1712 payload_expected += chunk_input
1713 bit_len_expected += len(chunk_input) * 8
1714 chunks_len_expected.append(len(chunk_input) + 1)
1716 chunks.append(chunk_constructed(chunk_input))
1717 payload = b"".join(chunk_input)
1718 payload_expected += payload
1719 bit_len_expected += len(payload) * 8
1720 for c in chunk_input:
1721 chunks_len_expected.append(len(c) + 1)
1722 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1723 chunk_last = BitString("'%s'B" % "".join(
1724 "1" if bit else "0" for bit in chunk_last_bits
1726 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1727 payload_expected += bytes(chunk_last)
1728 bit_len_expected += chunk_last.bit_len
1729 encoded_indefinite = (
1730 tag_encode(form=TagFormConstructed, num=impl) +
1733 chunk_last.encode() +
1736 encoded_definite = (
1737 tag_encode(form=TagFormConstructed, num=impl) +
1738 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1742 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1743 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1744 for lenindef_expected, encoded in (
1745 (True, encoded_indefinite),
1746 (False, encoded_definite),
1748 obj, tail = BitString(impl=tag_encode(impl)).decode(
1750 ctx={"bered": True},
1752 self.assertSequenceEqual(tail, junk)
1753 self.assertEqual(obj.bit_len, bit_len_expected)
1754 self.assertSequenceEqual(bytes(obj), payload_expected)
1755 self.assertTrue(obj.ber_encoded)
1756 self.assertEqual(obj.lenindef, lenindef_expected)
1757 self.assertTrue(obj.bered)
1759 self.assertTrue(obj.ber_encoded)
1760 self.assertEqual(obj.lenindef, lenindef_expected)
1761 self.assertTrue(obj.bered)
1762 self.assertEqual(len(encoded), obj.tlvlen)
1765 pprint(obj, big_blobs=True, with_decode_path=True)
1767 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1769 decode_path=decode_path,
1770 ctx={"bered": True},
1772 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1773 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1774 self.assertGreater(len(dp), len(decode_path))
1775 self.assertEqual(obj.vlen, chunk_len_expected)
1778 integers(min_value=0),
1781 def test_ber_definite_too_short(self, offset, decode_path):
1782 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1784 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1786 decode_path=decode_path,
1787 ctx={"bered": True},
1789 self.assertEqual(err.exception.decode_path, decode_path)
1790 self.assertEqual(err.exception.offset, offset)
1793 integers(min_value=0),
1796 def test_ber_definite_no_data(self, offset, decode_path):
1797 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1799 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1801 decode_path=decode_path,
1802 ctx={"bered": True},
1804 self.assertEqual(err.exception.decode_path, decode_path)
1805 self.assertEqual(err.exception.offset, offset)
1808 integers(min_value=0),
1810 integers(min_value=1, max_value=3),
1812 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1813 bs = BitString(b"data").encode()
1814 with self.assertRaises(NotEnoughData) as err:
1816 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1818 decode_path=decode_path,
1819 ctx={"bered": True},
1821 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1822 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1825 integers(min_value=0),
1827 integers(min_value=1, max_value=3),
1829 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1830 bs = BitString(b"data").encode()
1831 bs_longer = BitString(b"data-longer").encode()
1832 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1835 tag_encode(3, form=TagFormConstructed) +
1836 len_encode((chunks + 1) * len(bs)) +
1841 decode_path=decode_path,
1842 ctx={"bered": True},
1844 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1845 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1848 integers(min_value=0),
1851 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1852 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1854 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1856 decode_path=decode_path,
1857 ctx={"bered": True},
1859 self.assertEqual(err.exception.decode_path, decode_path)
1860 self.assertEqual(err.exception.offset, offset)
1862 @given(data_strategy())
1863 def test_ber_indefinite_not_multiple(self, d):
1864 bs_short = BitString("'A'H").encode()
1865 bs_full = BitString("'AA'H").encode()
1866 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1867 chunks.append(bs_short)
1868 d.draw(permutations(chunks))
1869 chunks.append(bs_short)
1870 offset = d.draw(integers(min_value=0))
1871 decode_path = d.draw(decode_path_strat)
1872 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1875 tag_encode(3, form=TagFormConstructed) +
1881 decode_path=decode_path,
1882 ctx={"bered": True},
1885 err.exception.decode_path,
1886 decode_path + (str(chunks.index(bs_short)),),
1889 err.exception.offset,
1890 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1893 def test_x690_vector(self):
1894 vector = BitString("'0A3B5F291CD'H")
1895 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1896 self.assertSequenceEqual(tail, b"")
1897 self.assertEqual(obj, vector)
1898 obj, tail = BitString().decode(
1899 hexdec("23800303000A3B0305045F291CD00000"),
1900 ctx={"bered": True},
1902 self.assertSequenceEqual(tail, b"")
1903 self.assertEqual(obj, vector)
1904 self.assertTrue(obj.ber_encoded)
1905 self.assertTrue(obj.lenindef)
1906 self.assertTrue(obj.bered)
1908 self.assertTrue(obj.ber_encoded)
1909 self.assertTrue(obj.lenindef)
1910 self.assertTrue(obj.bered)
1912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1913 @given(integers(min_value=1000, max_value=3000))
1914 def test_cer(self, data_len):
1915 data = urandom(data_len)
1916 encoded = encode_cer(BitString(data))
1917 ctx = {"bered": True}
1918 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1919 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1920 evgens_expected = data_len // 999
1921 if evgens_expected * 999 != data_len:
1922 evgens_expected += 1
1923 evgens_expected += 1
1924 self.assertEqual(len(evgens), evgens_expected)
1925 for (_, obj, _) in evgens[:-2]:
1926 self.assertEqual(obj.vlen, 1000)
1927 _, obj, _ = evgens[-2]
1928 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1932 def octet_string_values_strategy(draw, do_expl=False):
1933 bound_min, bound_max = sorted(draw(sets(
1934 integers(min_value=0, max_value=1 << 7),
1938 value = draw(one_of(
1940 binary(min_size=bound_min, max_size=bound_max),
1942 default = draw(one_of(
1944 binary(min_size=bound_min, max_size=bound_max),
1947 if draw(booleans()):
1948 bounds = (bound_min, bound_max)
1952 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1954 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1955 optional = draw(one_of(none(), booleans()))
1957 draw(integers(min_value=0)),
1958 draw(integers(min_value=0)),
1959 draw(integers(min_value=0)),
1961 return (value, bounds, impl, expl, default, optional, _decoded)
1964 class OctetStringInherited(OctetString):
1968 class TestOctetString(CommonMixin, TestCase):
1969 base_klass = OctetString
1971 def test_invalid_value_type(self):
1972 with self.assertRaises(InvalidValueType) as err:
1973 OctetString(text_type(123))
1977 def test_optional(self, optional):
1978 obj = OctetString(default=OctetString(b""), optional=optional)
1979 self.assertTrue(obj.optional)
1982 def test_ready(self, value):
1984 self.assertFalse(obj.ready)
1987 pprint(obj, big_blobs=True, with_decode_path=True)
1988 with self.assertRaises(ObjNotReady) as err:
1991 with self.assertRaises(ObjNotReady) as err:
1993 obj = OctetString(value)
1994 self.assertTrue(obj.ready)
1997 pprint(obj, big_blobs=True, with_decode_path=True)
1999 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2000 def test_comparison(self, value1, value2, tag1, tag2):
2001 for klass in (OctetString, OctetStringInherited):
2002 obj1 = klass(value1)
2003 obj2 = klass(value2)
2004 self.assertEqual(obj1 == obj2, value1 == value2)
2005 self.assertEqual(obj1 != obj2, value1 != value2)
2006 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2007 obj1 = klass(value1, impl=tag1)
2008 obj2 = klass(value1, impl=tag2)
2009 self.assertEqual(obj1 == obj2, tag1 == tag2)
2010 self.assertEqual(obj1 != obj2, tag1 != tag2)
2012 @given(lists(binary()))
2013 def test_sorted_works(self, values):
2014 self.assertSequenceEqual(
2015 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2019 @given(data_strategy())
2020 def test_bounds_satisfied(self, d):
2021 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2022 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2023 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2024 OctetString(value=value, bounds=(bound_min, bound_max))
2026 @given(data_strategy())
2027 def test_bounds_unsatisfied(self, d):
2028 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2029 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2030 value = d.draw(binary(max_size=bound_min - 1))
2031 with self.assertRaises(BoundsError) as err:
2032 OctetString(value=value, bounds=(bound_min, bound_max))
2034 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2035 OctetString(bounds=(bound_min, bound_max)).decode(
2036 OctetString(value).encode()
2039 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2040 OctetString(bounds=(bound_min, bound_max)).decode(
2041 encode2pass(OctetString(value))
2043 value = d.draw(binary(min_size=bound_max + 1))
2044 with self.assertRaises(BoundsError) as err:
2045 OctetString(value=value, bounds=(bound_min, bound_max))
2047 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2048 OctetString(bounds=(bound_min, bound_max)).decode(
2049 OctetString(value).encode()
2052 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2053 OctetString(bounds=(bound_min, bound_max)).decode(
2054 encode2pass(OctetString(value))
2057 @given(data_strategy())
2058 def test_call(self, d):
2059 for klass in (OctetString, OctetStringInherited):
2068 ) = d.draw(octet_string_values_strategy())
2069 obj_initial = klass(
2075 optional_initial or False,
2086 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2087 if (default is None) and (obj_initial.default is not None):
2090 (bounds is None) and
2091 (value is not None) and
2092 (bounds_initial is not None) and
2093 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2097 (bounds is None) and
2098 (default is not None) and
2099 (bounds_initial is not None) and
2100 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2103 obj = obj_initial(value, bounds, impl, expl, default, optional)
2105 value_expected = default if value is None else value
2107 default_initial if value_expected is None
2110 self.assertEqual(obj, value_expected)
2111 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2112 self.assertEqual(obj.expl_tag, expl or expl_initial)
2115 default_initial if default is None else default,
2117 if obj.default is None:
2118 optional = optional_initial if optional is None else optional
2119 optional = False if optional is None else optional
2122 self.assertEqual(obj.optional, optional)
2124 (obj._bound_min, obj._bound_max),
2125 bounds or bounds_initial or (0, float("+inf")),
2128 @given(octet_string_values_strategy())
2129 def test_copy(self, values):
2130 for klass in (OctetString, OctetStringInherited):
2131 obj = klass(*values)
2132 for copy_func in copy_funcs:
2133 obj_copied = copy_func(obj)
2134 self.assert_copied_basic_fields(obj, obj_copied)
2135 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2136 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2137 self.assertEqual(obj._value, obj_copied._value)
2141 integers(min_value=1).map(tag_encode),
2143 def test_stripped(self, value, tag_impl):
2144 obj = OctetString(value, impl=tag_impl)
2145 with self.assertRaises(NotEnoughData):
2146 obj.decode(obj.encode()[:-1])
2150 integers(min_value=1).map(tag_ctxc),
2152 def test_stripped_expl(self, value, tag_expl):
2153 obj = OctetString(value, expl=tag_expl)
2154 with self.assertRaises(NotEnoughData):
2155 obj.decode(obj.encode()[:-1])
2158 integers(min_value=31),
2159 integers(min_value=0),
2162 def test_bad_tag(self, tag, offset, decode_path):
2163 with self.assertRaises(DecodeError) as err:
2164 OctetString().decode(
2165 tag_encode(tag)[:-1],
2167 decode_path=decode_path,
2170 self.assertEqual(err.exception.offset, offset)
2171 self.assertEqual(err.exception.decode_path, decode_path)
2174 integers(min_value=128),
2175 integers(min_value=0),
2178 def test_bad_len(self, l, offset, decode_path):
2179 with self.assertRaises(DecodeError) as err:
2180 OctetString().decode(
2181 OctetString.tag_default + len_encode(l)[:-1],
2183 decode_path=decode_path,
2186 self.assertEqual(err.exception.offset, offset)
2187 self.assertEqual(err.exception.decode_path, decode_path)
2190 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2191 integers(min_value=0),
2194 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2195 value, bound_min = list(sorted(ints))
2197 class String(OctetString):
2198 bounds = (bound_min, bound_min)
2199 with self.assertRaises(DecodeError) as err:
2201 OctetString(b"\x00" * value).encode(),
2203 decode_path=decode_path,
2206 self.assertEqual(err.exception.offset, offset)
2207 self.assertEqual(err.exception.decode_path, decode_path)
2209 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2211 octet_string_values_strategy(),
2213 integers(min_value=1).map(tag_ctxc),
2214 integers(min_value=0),
2218 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2219 for klass in (OctetString, OctetStringInherited):
2220 _, _, _, _, default, optional, _decoded = values
2229 pprint(obj, big_blobs=True, with_decode_path=True)
2230 self.assertFalse(obj.expled)
2231 obj_encoded = obj.encode()
2232 self.assertEqual(encode2pass(obj), obj_encoded)
2233 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2234 obj_expled = obj(value, expl=tag_expl)
2235 self.assertTrue(obj_expled.expled)
2237 list(obj_expled.pps())
2238 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2239 obj_expled_encoded = obj_expled.encode()
2240 obj_expled_cer = encode_cer(obj_expled)
2241 self.assertNotEqual(obj_expled_cer, obj_encoded)
2242 self.assertSequenceEqual(
2243 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2246 ctx_copied = deepcopy(ctx_dummy)
2247 obj_decoded, tail = obj_expled.decode(
2248 obj_expled_encoded + tail_junk,
2252 self.assertDictEqual(ctx_copied, ctx_dummy)
2254 list(obj_decoded.pps())
2255 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2256 self.assertEqual(tail, tail_junk)
2257 self.assertEqual(obj_decoded, obj_expled)
2258 self.assertNotEqual(obj_decoded, obj)
2259 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2260 self.assertEqual(bytes(obj_decoded), bytes(obj))
2261 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2262 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2263 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2265 obj_decoded.expl_llen,
2266 len(len_encode(len(obj_encoded))),
2268 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2269 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2272 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2274 self.assertEqual(obj_decoded.expl_offset, offset)
2275 assert_exceeding_data(
2277 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2281 evgens = list(obj_expled.decode_evgen(
2282 obj_expled_encoded + tail_junk,
2284 decode_path=decode_path,
2287 self.assertEqual(len(evgens), 1)
2288 _decode_path, obj, tail = evgens[0]
2289 self.assertSequenceEqual(tail, tail_junk)
2290 self.assertEqual(_decode_path, decode_path)
2291 self.assertEqual(obj.expl_offset, offset)
2295 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2297 integers(min_value=1, max_value=30),
2300 binary(min_size=1, max_size=5),
2302 binary(min_size=1, max_size=5),
2313 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2314 def chunk_constructed(contents):
2316 tag_encode(form=TagFormConstructed, num=4) +
2318 b"".join(OctetString(content).encode() for content in contents) +
2322 chunks_len_expected = []
2323 payload_expected = b""
2324 for chunk_input in chunk_inputs:
2325 if isinstance(chunk_input, binary_type):
2326 chunks.append(OctetString(chunk_input).encode())
2327 payload_expected += chunk_input
2328 chunks_len_expected.append(len(chunk_input))
2330 chunks.append(chunk_constructed(chunk_input))
2331 payload = b"".join(chunk_input)
2332 payload_expected += payload
2333 for c in chunk_input:
2334 chunks_len_expected.append(len(c))
2335 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2336 encoded_indefinite = (
2337 tag_encode(form=TagFormConstructed, num=impl) +
2342 encoded_definite = (
2343 tag_encode(form=TagFormConstructed, num=impl) +
2344 len_encode(len(b"".join(chunks))) +
2347 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2348 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2349 for lenindef_expected, encoded in (
2350 (True, encoded_indefinite),
2351 (False, encoded_definite),
2353 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2355 ctx={"bered": True},
2357 self.assertSequenceEqual(tail, junk)
2358 self.assertSequenceEqual(bytes(obj), payload_expected)
2359 self.assertTrue(obj.ber_encoded)
2360 self.assertEqual(obj.lenindef, lenindef_expected)
2361 self.assertTrue(obj.bered)
2363 self.assertTrue(obj.ber_encoded)
2364 self.assertEqual(obj.lenindef, lenindef_expected)
2365 self.assertTrue(obj.bered)
2366 self.assertEqual(len(encoded), obj.tlvlen)
2369 pprint(obj, big_blobs=True, with_decode_path=True)
2371 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2373 decode_path=decode_path,
2374 ctx={"bered": True},
2376 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2377 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2378 self.assertGreater(len(dp), len(decode_path))
2379 self.assertEqual(obj.vlen, chunk_len_expected)
2382 integers(min_value=0),
2385 def test_ber_definite_too_short(self, offset, decode_path):
2386 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2387 OctetString().decode(
2388 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2390 decode_path=decode_path,
2391 ctx={"bered": True},
2393 self.assertEqual(err.exception.decode_path, decode_path)
2394 self.assertEqual(err.exception.offset, offset)
2397 integers(min_value=0),
2399 integers(min_value=1, max_value=3),
2401 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2402 bs = OctetString(b"data").encode()
2403 with self.assertRaises(NotEnoughData) as err:
2404 OctetString().decode(
2405 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2407 decode_path=decode_path,
2408 ctx={"bered": True},
2410 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2411 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2414 integers(min_value=0),
2416 integers(min_value=1, max_value=3),
2418 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2419 bs = OctetString(b"data").encode()
2420 bs_longer = OctetString(b"data-longer").encode()
2421 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2422 OctetString().decode(
2424 tag_encode(4, form=TagFormConstructed) +
2425 len_encode((chunks + 1) * len(bs)) +
2430 decode_path=decode_path,
2431 ctx={"bered": True},
2433 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2434 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2436 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2437 @given(integers(min_value=1001, max_value=3000))
2438 def test_cer(self, data_len):
2439 data = urandom(data_len)
2440 encoded = encode_cer(OctetString(data))
2441 ctx = {"bered": True}
2442 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2443 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2444 evgens_expected = data_len // 1000
2445 if evgens_expected * 1000 != data_len:
2446 evgens_expected += 1
2447 evgens_expected += 1
2448 self.assertEqual(len(evgens), evgens_expected)
2449 for (_, obj, _) in evgens[:-2]:
2450 self.assertEqual(obj.vlen, 1000)
2451 _, obj, _ = evgens[-2]
2452 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2456 def null_values_strategy(draw, do_expl=False):
2460 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2462 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2463 optional = draw(one_of(none(), booleans()))
2465 draw(integers(min_value=0)),
2466 draw(integers(min_value=0)),
2467 draw(integers(min_value=0)),
2469 return (impl, expl, optional, _decoded)
2472 class NullInherited(Null):
2476 class TestNull(CommonMixin, TestCase):
2479 def test_ready(self):
2481 self.assertTrue(obj.ready)
2484 pprint(obj, big_blobs=True, with_decode_path=True)
2486 @given(binary(min_size=1), binary(min_size=1))
2487 def test_comparison(self, tag1, tag2):
2488 for klass in (Null, NullInherited):
2489 obj1 = klass(impl=tag1)
2490 obj2 = klass(impl=tag2)
2491 self.assertEqual(obj1 == obj2, tag1 == tag2)
2492 self.assertEqual(obj1 != obj2, tag1 != tag2)
2493 self.assertNotEqual(obj1, tag2)
2495 @given(data_strategy())
2496 def test_call(self, d):
2497 for klass in (Null, NullInherited):
2503 ) = d.draw(null_values_strategy())
2504 obj_initial = klass(
2507 optional=optional_initial or False,
2508 _decoded=_decoded_initial,
2515 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2516 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2517 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2518 self.assertEqual(obj.expl_tag, expl or expl_initial)
2519 optional = optional_initial if optional is None else optional
2520 optional = False if optional is None else optional
2521 self.assertEqual(obj.optional, optional)
2523 @given(null_values_strategy())
2524 def test_copy(self, values):
2525 for klass in (Null, NullInherited):
2526 impl, expl, optional, _decoded = values
2530 optional=optional or False,
2533 for copy_func in copy_funcs:
2534 obj_copied = copy_func(obj)
2535 self.assert_copied_basic_fields(obj, obj_copied)
2537 @given(integers(min_value=1).map(tag_encode))
2538 def test_stripped(self, tag_impl):
2539 obj = Null(impl=tag_impl)
2540 with self.assertRaises(NotEnoughData):
2541 obj.decode(obj.encode()[:-1])
2543 @given(integers(min_value=1).map(tag_ctxc))
2544 def test_stripped_expl(self, tag_expl):
2545 obj = Null(expl=tag_expl)
2546 with self.assertRaises(NotEnoughData):
2547 obj.decode(obj.encode()[:-1])
2550 integers(min_value=31),
2551 integers(min_value=0),
2554 def test_bad_tag(self, tag, offset, decode_path):
2555 with self.assertRaises(DecodeError) as err:
2557 tag_encode(tag)[:-1],
2559 decode_path=decode_path,
2562 self.assertEqual(err.exception.offset, offset)
2563 self.assertEqual(err.exception.decode_path, decode_path)
2566 integers(min_value=128),
2567 integers(min_value=0),
2570 def test_bad_len(self, l, offset, decode_path):
2571 with self.assertRaises(DecodeError) as err:
2573 Null.tag_default + len_encode(l)[:-1],
2575 decode_path=decode_path,
2578 self.assertEqual(err.exception.offset, offset)
2579 self.assertEqual(err.exception.decode_path, decode_path)
2581 @given(binary(min_size=1))
2582 def test_tag_mismatch(self, impl):
2583 assume(impl != Null.tag_default)
2584 with self.assertRaises(TagMismatch):
2585 Null(impl=impl).decode(Null().encode())
2588 null_values_strategy(),
2589 integers(min_value=1).map(tag_ctxc),
2590 integers(min_value=0),
2594 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2595 for klass in (Null, NullInherited):
2596 _, _, optional, _decoded = values
2597 obj = klass(optional=optional, _decoded=_decoded)
2600 pprint(obj, big_blobs=True, with_decode_path=True)
2601 self.assertFalse(obj.expled)
2602 obj_encoded = obj.encode()
2603 self.assertEqual(encode2pass(obj), obj_encoded)
2604 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2605 obj_expled = obj(expl=tag_expl)
2606 self.assertTrue(obj_expled.expled)
2608 list(obj_expled.pps())
2609 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2610 obj_expled_encoded = obj_expled.encode()
2611 obj_expled_cer = encode_cer(obj_expled)
2612 self.assertNotEqual(obj_expled_cer, obj_encoded)
2613 self.assertSequenceEqual(
2614 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2617 ctx_copied = deepcopy(ctx_dummy)
2618 obj_decoded, tail = obj_expled.decode(
2619 obj_expled_encoded + tail_junk,
2623 self.assertDictEqual(ctx_copied, ctx_dummy)
2625 list(obj_decoded.pps())
2626 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2627 self.assertEqual(tail, tail_junk)
2628 self.assertEqual(obj_decoded, obj_expled)
2629 self.assertNotEqual(obj_decoded, obj)
2630 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2631 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2632 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2634 obj_decoded.expl_llen,
2635 len(len_encode(len(obj_encoded))),
2637 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2638 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2641 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2643 self.assertEqual(obj_decoded.expl_offset, offset)
2644 assert_exceeding_data(
2646 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2650 evgens = list(obj_expled.decode_evgen(
2651 obj_expled_encoded + tail_junk,
2653 decode_path=decode_path,
2656 self.assertEqual(len(evgens), 1)
2657 _decode_path, obj, tail = evgens[0]
2658 self.assertSequenceEqual(tail, tail_junk)
2659 self.assertEqual(_decode_path, decode_path)
2660 self.assertEqual(obj, obj_decoded)
2661 self.assertEqual(obj.expl_offset, offset)
2666 @given(integers(min_value=1))
2667 def test_invalid_len(self, l):
2668 with self.assertRaises(InvalidLength):
2669 Null().decode(b"".join((
2676 def oid_strategy(draw):
2677 first_arc = draw(integers(min_value=0, max_value=2))
2679 if first_arc in (0, 1):
2680 second_arc = draw(integers(min_value=0, max_value=39))
2682 second_arc = draw(integers(min_value=0))
2683 other_arcs = draw(lists(integers(min_value=0)))
2684 return tuple([first_arc, second_arc] + other_arcs)
2688 def oid_values_strategy(draw, do_expl=False):
2689 value = draw(one_of(none(), oid_strategy()))
2693 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2695 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2696 default = draw(one_of(none(), oid_strategy()))
2697 optional = draw(one_of(none(), booleans()))
2699 draw(integers(min_value=0)),
2700 draw(integers(min_value=0)),
2701 draw(integers(min_value=0)),
2703 return (value, impl, expl, default, optional, _decoded)
2706 class ObjectIdentifierInherited(ObjectIdentifier):
2710 class TestObjectIdentifier(CommonMixin, TestCase):
2711 base_klass = ObjectIdentifier
2713 def test_invalid_value_type(self):
2714 with self.assertRaises(InvalidValueType) as err:
2715 ObjectIdentifier(123)
2719 def test_optional(self, optional):
2720 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2721 self.assertTrue(obj.optional)
2723 @given(oid_strategy())
2724 def test_ready(self, value):
2725 obj = ObjectIdentifier()
2726 self.assertFalse(obj.ready)
2729 pprint(obj, big_blobs=True, with_decode_path=True)
2730 with self.assertRaises(ObjNotReady) as err:
2733 with self.assertRaises(ObjNotReady) as err:
2735 obj = ObjectIdentifier(value)
2736 self.assertTrue(obj.ready)
2737 self.assertFalse(obj.ber_encoded)
2740 pprint(obj, big_blobs=True, with_decode_path=True)
2743 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2744 def test_comparison(self, value1, value2, tag1, tag2):
2745 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2746 obj1 = klass(value1)
2747 obj2 = klass(value2)
2748 self.assertEqual(obj1 == obj2, value1 == value2)
2749 self.assertEqual(obj1 != obj2, value1 != value2)
2750 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2751 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2752 obj1 = klass(value1, impl=tag1)
2753 obj2 = klass(value1, impl=tag2)
2754 self.assertEqual(obj1 == obj2, tag1 == tag2)
2755 self.assertEqual(obj1 != obj2, tag1 != tag2)
2757 @given(lists(oid_strategy()))
2758 def test_sorted_works(self, values):
2759 self.assertSequenceEqual(
2760 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2764 @given(data_strategy())
2765 def test_call(self, d):
2766 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2774 ) = d.draw(oid_values_strategy())
2775 obj_initial = klass(
2776 value=value_initial,
2779 default=default_initial,
2780 optional=optional_initial or False,
2781 _decoded=_decoded_initial,
2790 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2799 value_expected = default if value is None else value
2801 default_initial if value_expected is None
2804 self.assertEqual(obj, value_expected)
2805 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2806 self.assertEqual(obj.expl_tag, expl or expl_initial)
2809 default_initial if default is None else default,
2811 if obj.default is None:
2812 optional = optional_initial if optional is None else optional
2813 optional = False if optional is None else optional
2816 self.assertEqual(obj.optional, optional)
2818 @given(oid_values_strategy())
2819 def test_copy(self, values):
2820 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2837 for copy_func in copy_funcs:
2838 obj_copied = copy_func(obj)
2839 self.assert_copied_basic_fields(obj, obj_copied)
2840 self.assertEqual(obj._value, obj_copied._value)
2842 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2845 integers(min_value=1).map(tag_encode),
2847 def test_stripped(self, value, tag_impl):
2848 obj = ObjectIdentifier(value, impl=tag_impl)
2849 with self.assertRaises(NotEnoughData):
2850 obj.decode(obj.encode()[:-1])
2854 integers(min_value=1).map(tag_ctxc),
2856 def test_stripped_expl(self, value, tag_expl):
2857 obj = ObjectIdentifier(value, expl=tag_expl)
2858 with self.assertRaises(NotEnoughData):
2859 obj.decode(obj.encode()[:-1])
2862 integers(min_value=31),
2863 integers(min_value=0),
2866 def test_bad_tag(self, tag, offset, decode_path):
2867 with self.assertRaises(DecodeError) as err:
2868 ObjectIdentifier().decode(
2869 tag_encode(tag)[:-1],
2871 decode_path=decode_path,
2874 self.assertEqual(err.exception.offset, offset)
2875 self.assertEqual(err.exception.decode_path, decode_path)
2878 integers(min_value=128),
2879 integers(min_value=0),
2882 def test_bad_len(self, l, offset, decode_path):
2883 with self.assertRaises(DecodeError) as err:
2884 ObjectIdentifier().decode(
2885 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2887 decode_path=decode_path,
2890 self.assertEqual(err.exception.offset, offset)
2891 self.assertEqual(err.exception.decode_path, decode_path)
2893 def test_zero_oid(self):
2894 with self.assertRaises(NotEnoughData):
2895 ObjectIdentifier().decode(
2896 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2899 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2900 @given(oid_strategy())
2901 def test_unfinished_oid(self, value):
2902 assume(list(value)[-1] > 255)
2903 obj_encoded = ObjectIdentifier(value).encode()
2904 obj, _ = ObjectIdentifier().decode(obj_encoded)
2905 data = obj_encoded[obj.tlen + obj.llen:-1]
2907 ObjectIdentifier.tag_default,
2908 len_encode(len(data)),
2911 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2914 @given(integers(min_value=0))
2915 def test_invalid_short(self, value):
2916 with self.assertRaises(InvalidOID):
2917 ObjectIdentifier((value,))
2918 with self.assertRaises(InvalidOID):
2919 ObjectIdentifier("%d" % value)
2921 @given(integers(min_value=3), integers(min_value=0))
2922 def test_invalid_first_arc(self, first_arc, second_arc):
2923 with self.assertRaises(InvalidOID):
2924 ObjectIdentifier((first_arc, second_arc))
2925 with self.assertRaises(InvalidOID):
2926 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2928 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2929 def test_invalid_second_arc(self, first_arc, second_arc):
2930 with self.assertRaises(InvalidOID):
2931 ObjectIdentifier((first_arc, second_arc))
2932 with self.assertRaises(InvalidOID):
2933 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2935 @given(text(alphabet=ascii_letters + ".", min_size=1))
2936 def test_junk(self, oid):
2937 with self.assertRaises(InvalidOID):
2938 ObjectIdentifier(oid)
2940 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2941 @given(oid_strategy())
2942 def test_validness(self, oid):
2943 obj = ObjectIdentifier(oid)
2944 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2947 pprint(obj, big_blobs=True, with_decode_path=True)
2949 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2951 oid_values_strategy(),
2953 integers(min_value=1).map(tag_ctxc),
2954 integers(min_value=0),
2958 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2959 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2960 _, _, _, default, optional, _decoded = values
2969 pprint(obj, big_blobs=True, with_decode_path=True)
2970 self.assertFalse(obj.expled)
2971 obj_encoded = obj.encode()
2972 self.assertEqual(encode2pass(obj), obj_encoded)
2973 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2974 obj_expled = obj(value, expl=tag_expl)
2975 self.assertTrue(obj_expled.expled)
2977 list(obj_expled.pps())
2978 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2979 obj_expled_encoded = obj_expled.encode()
2980 obj_expled_cer = encode_cer(obj_expled)
2981 self.assertNotEqual(obj_expled_cer, obj_encoded)
2982 self.assertSequenceEqual(
2983 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2986 ctx_copied = deepcopy(ctx_dummy)
2987 obj_decoded, tail = obj_expled.decode(
2988 obj_expled_encoded + tail_junk,
2992 self.assertDictEqual(ctx_copied, ctx_dummy)
2994 list(obj_decoded.pps())
2995 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2996 self.assertEqual(tail, tail_junk)
2997 self.assertEqual(obj_decoded, obj_expled)
2998 self.assertNotEqual(obj_decoded, obj)
2999 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
3000 self.assertEqual(tuple(obj_decoded), tuple(obj))
3001 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3002 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3003 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3005 obj_decoded.expl_llen,
3006 len(len_encode(len(obj_encoded))),
3008 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3009 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3012 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3014 self.assertEqual(obj_decoded.expl_offset, offset)
3015 assert_exceeding_data(
3017 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3021 evgens = list(obj_expled.decode_evgen(
3022 obj_expled_encoded + tail_junk,
3024 decode_path=decode_path,
3027 self.assertEqual(len(evgens), 1)
3028 _decode_path, obj, tail = evgens[0]
3029 self.assertSequenceEqual(tail, tail_junk)
3030 self.assertEqual(_decode_path, decode_path)
3031 self.assertEqual(obj, obj_decoded)
3032 self.assertEqual(obj.expl_offset, offset)
3037 oid_strategy().map(ObjectIdentifier),
3038 oid_strategy().map(ObjectIdentifier),
3040 def test_add(self, oid1, oid2):
3041 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3042 for oid_to_add in (oid2, tuple(oid2)):
3043 self.assertEqual(oid1 + oid_to_add, oid_expect)
3044 with self.assertRaises(InvalidValueType):
3047 def test_go_vectors_valid(self):
3048 for data, expect in (
3050 (b"\x55\x02", (2, 5, 2)),
3051 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3052 (b"\x81\x34\x03", (2, 100, 3)),
3055 ObjectIdentifier().decode(b"".join((
3056 ObjectIdentifier.tag_default,
3057 len_encode(len(data)),
3063 def test_go_vectors_invalid(self):
3064 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3065 with self.assertRaises(DecodeError):
3066 ObjectIdentifier().decode(b"".join((
3067 Integer.tag_default,
3068 len_encode(len(data)),
3072 def test_x690_vector(self):
3074 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3075 ObjectIdentifier((2, 999, 3)),
3078 def test_nonnormalized_first_arc(self):
3080 ObjectIdentifier.tag_default +
3083 ObjectIdentifier((1, 0)).encode()[-1:]
3085 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3086 self.assertTrue(obj.ber_encoded)
3087 self.assertTrue(obj.bered)
3089 self.assertTrue(obj.ber_encoded)
3090 self.assertTrue(obj.bered)
3091 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3092 ObjectIdentifier().decode(tampered)
3094 @given(data_strategy())
3095 def test_negative_arcs(self, d):
3096 oid = list(d.draw(oid_strategy()))
3099 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3101 if oid[idx - 1] == 0:
3103 with self.assertRaises(InvalidOID):
3104 ObjectIdentifier(tuple(oid))
3105 with self.assertRaises(InvalidOID):
3106 ObjectIdentifier(".".join(str(i) for i in oid))
3108 @given(data_strategy())
3109 def test_plused_arcs(self, d):
3110 oid = [str(arc) for arc in d.draw(oid_strategy())]
3111 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3112 oid[idx - 1] = "+" + oid[idx - 1]
3113 with self.assertRaises(InvalidOID):
3114 ObjectIdentifier(".".join(str(i) for i in oid))
3116 @given(data_strategy())
3117 def test_nonnormalized_arcs(self, d):
3118 arcs = d.draw(lists(
3119 integers(min_value=0, max_value=100),
3123 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3124 _, _, lv = tag_strip(dered)
3125 _, _, v = len_decode(lv)
3126 v_no_first_arc = v[1:]
3127 idx_for_tamper = d.draw(integers(
3129 max_value=len(v_no_first_arc) - 1,
3131 tampered = list(bytearray(v_no_first_arc))
3132 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3133 tampered.insert(idx_for_tamper, 0x80)
3134 tampered = bytes(bytearray(tampered))
3136 ObjectIdentifier.tag_default +
3137 len_encode(len(tampered)) +
3140 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3141 self.assertTrue(obj.ber_encoded)
3142 self.assertTrue(obj.bered)
3144 self.assertTrue(obj.ber_encoded)
3145 self.assertTrue(obj.bered)
3146 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3147 ObjectIdentifier().decode(tampered)
3151 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3153 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3154 values = list(draw(sets(
3156 min_size=len(schema),
3157 max_size=len(schema),
3159 schema = list(zip(schema, values))
3160 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3164 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3166 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3167 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3168 optional = draw(one_of(none(), booleans()))
3170 draw(integers(min_value=0)),
3171 draw(integers(min_value=0)),
3172 draw(integers(min_value=0)),
3174 return (schema, value, impl, expl, default, optional, _decoded)
3177 class TestEnumerated(CommonMixin, TestCase):
3178 class EWhatever(Enumerated):
3179 schema = (("whatever", 0),)
3181 base_klass = EWhatever
3183 def test_schema_required(self):
3184 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3187 def test_invalid_value_type(self):
3188 with self.assertRaises(InvalidValueType) as err:
3189 self.base_klass((1, 2))
3192 @given(sets(text_letters(), min_size=2))
3193 def test_unknown_name(self, schema_input):
3194 missing = schema_input.pop()
3196 class E(Enumerated):
3197 schema = [(n, 123) for n in schema_input]
3198 with self.assertRaises(ObjUnknown) as err:
3203 sets(text_letters(), min_size=2),
3204 sets(integers(), min_size=2),
3206 def test_unknown_value(self, schema_input, values_input):
3208 missing_value = values_input.pop()
3209 _input = list(zip(schema_input, values_input))
3211 class E(Enumerated):
3213 with self.assertRaises(DecodeError) as err:
3218 def test_optional(self, optional):
3219 obj = self.base_klass(default="whatever", optional=optional)
3220 self.assertTrue(obj.optional)
3222 def test_ready(self):
3223 obj = self.base_klass()
3224 self.assertFalse(obj.ready)
3227 pprint(obj, big_blobs=True, with_decode_path=True)
3228 with self.assertRaises(ObjNotReady) as err:
3231 obj = self.base_klass("whatever")
3232 self.assertTrue(obj.ready)
3235 pprint(obj, big_blobs=True, with_decode_path=True)
3237 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3238 def test_comparison(self, value1, value2, tag1, tag2):
3239 class E(Enumerated):
3241 ("whatever0", value1),
3242 ("whatever1", value2),
3245 class EInherited(E):
3247 for klass in (E, EInherited):
3248 obj1 = klass(value1)
3249 obj2 = klass(value2)
3250 self.assertEqual(obj1 == obj2, value1 == value2)
3251 self.assertEqual(obj1 != obj2, value1 != value2)
3252 self.assertEqual(obj1 == int(obj2), value1 == value2)
3253 obj1 = klass(value1, impl=tag1)
3254 obj2 = klass(value1, impl=tag2)
3255 self.assertEqual(obj1 == obj2, tag1 == tag2)
3256 self.assertEqual(obj1 != obj2, tag1 != tag2)
3258 @given(data_strategy())
3259 def test_call(self, d):
3268 ) = d.draw(enumerated_values_strategy())
3270 class E(Enumerated):
3271 schema = schema_initial
3273 value=value_initial,
3276 default=default_initial,
3277 optional=optional_initial or False,
3278 _decoded=_decoded_initial,
3288 ) = d.draw(enumerated_values_strategy(
3289 schema=schema_initial,
3290 do_expl=impl_initial is None,
3300 value_expected = default if value is None else value
3302 default_initial if value_expected is None
3307 dict(schema_initial).get(value_expected, value_expected),
3309 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3310 self.assertEqual(obj.expl_tag, expl or expl_initial)
3313 default_initial if default is None else default,
3315 if obj.default is None:
3316 optional = optional_initial if optional is None else optional
3317 optional = False if optional is None else optional
3320 self.assertEqual(obj.optional, optional)
3321 self.assertEqual(obj.specs, dict(schema_initial))
3323 @given(enumerated_values_strategy())
3324 def test_copy(self, values):
3325 schema_input, value, impl, expl, default, optional, _decoded = values
3327 class E(Enumerated):
3328 schema = schema_input
3338 for copy_func in copy_funcs:
3339 obj_copied = copy_func(obj)
3340 self.assert_copied_basic_fields(obj, obj_copied)
3341 self.assertEqual(obj.specs, obj_copied.specs)
3343 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3344 @given(data_strategy())
3345 def test_symmetric(self, d):
3346 schema_input, _, _, _, default, optional, _decoded = d.draw(
3347 enumerated_values_strategy(),
3349 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3350 offset = d.draw(integers(min_value=0))
3351 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3352 tail_junk = d.draw(binary(max_size=5))
3353 decode_path = d.draw(decode_path_strat)
3355 class E(Enumerated):
3356 schema = schema_input
3365 pprint(obj, big_blobs=True, with_decode_path=True)
3366 self.assertFalse(obj.expled)
3367 obj_encoded = obj.encode()
3368 self.assertEqual(encode2pass(obj), obj_encoded)
3369 obj_expled = obj(value, expl=tag_expl)
3370 self.assertTrue(obj_expled.expled)
3372 list(obj_expled.pps())
3373 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3374 obj_expled_encoded = obj_expled.encode()
3375 ctx_copied = deepcopy(ctx_dummy)
3376 obj_decoded, tail = obj_expled.decode(
3377 obj_expled_encoded + tail_junk,
3381 self.assertDictEqual(ctx_copied, ctx_dummy)
3383 list(obj_decoded.pps())
3384 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3385 self.assertEqual(tail, tail_junk)
3386 self.assertEqual(obj_decoded, obj_expled)
3387 self.assertNotEqual(obj_decoded, obj)
3388 self.assertEqual(int(obj_decoded), int(obj_expled))
3389 self.assertEqual(int(obj_decoded), int(obj))
3390 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3391 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3392 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3394 obj_decoded.expl_llen,
3395 len(len_encode(len(obj_encoded))),
3397 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3398 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3401 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3403 self.assertEqual(obj_decoded.expl_offset, offset)
3404 assert_exceeding_data(
3406 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3410 evgens = list(obj_expled.decode_evgen(
3411 obj_expled_encoded + tail_junk,
3413 decode_path=decode_path,
3416 self.assertEqual(len(evgens), 1)
3417 _decode_path, obj, tail = evgens[0]
3418 self.assertSequenceEqual(tail, tail_junk)
3419 self.assertEqual(_decode_path, decode_path)
3420 self.assertEqual(obj, obj_decoded)
3421 self.assertEqual(obj.expl_offset, offset)
3427 def string_values_strategy(draw, alphabet, do_expl=False):
3428 bound_min, bound_max = sorted(draw(sets(
3429 integers(min_value=0, max_value=1 << 7),
3433 value = draw(one_of(
3435 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3437 default = draw(one_of(
3439 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3442 if draw(booleans()):
3443 bounds = (bound_min, bound_max)
3447 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3449 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3450 optional = draw(one_of(none(), booleans()))
3452 draw(integers(min_value=0)),
3453 draw(integers(min_value=0)),
3454 draw(integers(min_value=0)),
3456 return (value, bounds, impl, expl, default, optional, _decoded)
3459 class StringMixin(object):
3460 def test_invalid_value_type(self):
3461 with self.assertRaises(InvalidValueType) as err:
3462 self.base_klass((1, 2))
3465 def text_alphabet(self):
3466 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
3467 return printable + whitespace
3471 def test_optional(self, optional):
3472 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3473 self.assertTrue(obj.optional)
3475 @given(data_strategy())
3476 def test_ready(self, d):
3477 obj = self.base_klass()
3478 self.assertFalse(obj.ready)
3481 pprint(obj, big_blobs=True, with_decode_path=True)
3483 with self.assertRaises(ObjNotReady) as err:
3486 with self.assertRaises(ObjNotReady) as err:
3488 value = d.draw(text(alphabet=self.text_alphabet()))
3489 obj = self.base_klass(value)
3490 self.assertTrue(obj.ready)
3493 pprint(obj, big_blobs=True, with_decode_path=True)
3496 @given(data_strategy())
3497 def test_comparison(self, d):
3498 value1 = d.draw(text(alphabet=self.text_alphabet()))
3499 value2 = d.draw(text(alphabet=self.text_alphabet()))
3500 tag1 = d.draw(binary(min_size=1))
3501 tag2 = d.draw(binary(min_size=1))
3502 obj1 = self.base_klass(value1)
3503 obj2 = self.base_klass(value2)
3504 self.assertEqual(obj1 == obj2, value1 == value2)
3505 self.assertEqual(obj1 != obj2, value1 != value2)
3506 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3507 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3508 obj1 = self.base_klass(value1, impl=tag1)
3509 obj2 = self.base_klass(value1, impl=tag2)
3510 self.assertEqual(obj1 == obj2, tag1 == tag2)
3511 self.assertEqual(obj1 != obj2, tag1 != tag2)
3513 @given(data_strategy())
3514 def test_bounds_satisfied(self, d):
3515 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3516 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3517 value = d.draw(text(
3518 alphabet=self.text_alphabet(),
3522 self.base_klass(value=value, bounds=(bound_min, bound_max))
3524 @given(data_strategy())
3525 def test_bounds_unsatisfied(self, d):
3526 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3527 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3528 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3529 with self.assertRaises(BoundsError) as err:
3530 self.base_klass(value=value, bounds=(bound_min, bound_max))
3532 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3533 self.base_klass(bounds=(bound_min, bound_max)).decode(
3534 self.base_klass(value).encode()
3537 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3538 self.base_klass(bounds=(bound_min, bound_max)).decode(
3539 encode2pass(self.base_klass(value))
3541 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3542 with self.assertRaises(BoundsError) as err:
3543 self.base_klass(value=value, bounds=(bound_min, bound_max))
3545 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3546 self.base_klass(bounds=(bound_min, bound_max)).decode(
3547 self.base_klass(value).encode()
3550 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3551 self.base_klass(bounds=(bound_min, bound_max)).decode(
3552 encode2pass(self.base_klass(value))
3555 @given(data_strategy())
3556 def test_call(self, d):
3565 ) = d.draw(string_values_strategy(self.text_alphabet()))
3566 obj_initial = self.base_klass(
3572 optional_initial or False,
3583 ) = d.draw(string_values_strategy(
3584 self.text_alphabet(),
3585 do_expl=impl_initial is None,
3587 if (default is None) and (obj_initial.default is not None):
3590 (bounds is None) and
3591 (value is not None) and
3592 (bounds_initial is not None) and
3593 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3597 (bounds is None) and
3598 (default is not None) and
3599 (bounds_initial is not None) and
3600 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3603 obj = obj_initial(value, bounds, impl, expl, default, optional)
3605 value_expected = default if value is None else value
3607 default_initial if value_expected is None
3610 self.assertEqual(obj, value_expected)
3611 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3612 self.assertEqual(obj.expl_tag, expl or expl_initial)
3615 default_initial if default is None else default,
3617 if obj.default is None:
3618 optional = optional_initial if optional is None else optional
3619 optional = False if optional is None else optional
3622 self.assertEqual(obj.optional, optional)
3624 (obj._bound_min, obj._bound_max),
3625 bounds or bounds_initial or (0, float("+inf")),
3628 @given(data_strategy())
3629 def test_copy(self, d):
3630 values = d.draw(string_values_strategy(self.text_alphabet()))
3631 obj = self.base_klass(*values)
3632 for copy_func in copy_funcs:
3633 obj_copied = copy_func(obj)
3634 self.assert_copied_basic_fields(obj, obj_copied)
3635 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3636 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3637 self.assertEqual(obj._value, obj_copied._value)
3639 @given(data_strategy())
3640 def test_stripped(self, d):
3641 value = d.draw(text(alphabet=self.text_alphabet()))
3642 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3643 obj = self.base_klass(value, impl=tag_impl)
3644 with self.assertRaises(NotEnoughData):
3645 obj.decode(obj.encode()[:-1])
3647 @given(data_strategy())
3648 def test_stripped_expl(self, d):
3649 value = d.draw(text(alphabet=self.text_alphabet()))
3650 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3651 obj = self.base_klass(value, expl=tag_expl)
3652 with self.assertRaises(NotEnoughData):
3653 obj.decode(obj.encode()[:-1])
3656 integers(min_value=31),
3657 integers(min_value=0),
3660 def test_bad_tag(self, tag, offset, decode_path):
3661 with self.assertRaises(DecodeError) as err:
3662 self.base_klass().decode(
3663 tag_encode(tag)[:-1],
3665 decode_path=decode_path,
3668 self.assertEqual(err.exception.offset, offset)
3669 self.assertEqual(err.exception.decode_path, decode_path)
3672 integers(min_value=128),
3673 integers(min_value=0),
3676 def test_bad_len(self, l, offset, decode_path):
3677 with self.assertRaises(DecodeError) as err:
3678 self.base_klass().decode(
3679 self.base_klass.tag_default + len_encode(l)[:-1],
3681 decode_path=decode_path,
3684 self.assertEqual(err.exception.offset, offset)
3685 self.assertEqual(err.exception.decode_path, decode_path)
3688 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3689 integers(min_value=0),
3692 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3693 value, bound_min = list(sorted(ints))
3695 class String(self.base_klass):
3696 # Multiply this value by four, to satisfy UTF-32 bounds
3697 # (4 bytes per character) validation
3698 bounds = (bound_min * 4, bound_min * 4)
3699 with self.assertRaises(DecodeError) as err:
3701 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3703 decode_path=decode_path,
3706 self.assertEqual(err.exception.offset, offset)
3707 self.assertEqual(err.exception.decode_path, decode_path)
3709 @given(data_strategy())
3710 def test_symmetric(self, d):
3711 values = d.draw(string_values_strategy(self.text_alphabet()))
3712 value = d.draw(text(alphabet=self.text_alphabet()))
3713 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3714 offset = d.draw(integers(min_value=0))
3715 tail_junk = d.draw(binary(max_size=5))
3716 decode_path = d.draw(decode_path_strat)
3717 _, _, _, _, default, optional, _decoded = values
3718 obj = self.base_klass(
3726 pprint(obj, big_blobs=True, with_decode_path=True)
3727 self.assertFalse(obj.expled)
3728 obj_encoded = obj.encode()
3729 self.assertEqual(encode2pass(obj), obj_encoded)
3730 obj_expled = obj(value, expl=tag_expl)
3731 self.assertTrue(obj_expled.expled)
3733 list(obj_expled.pps())
3734 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3735 obj_expled_encoded = obj_expled.encode()
3736 ctx_copied = deepcopy(ctx_dummy)
3737 obj_decoded, tail = obj_expled.decode(
3738 obj_expled_encoded + tail_junk,
3742 self.assertDictEqual(ctx_copied, ctx_dummy)
3744 list(obj_decoded.pps())
3745 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3746 self.assertEqual(tail, tail_junk)
3747 self.assertEqual(obj_decoded, obj_expled)
3748 self.assertNotEqual(obj_decoded, obj)
3749 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3750 self.assertEqual(bytes(obj_decoded), bytes(obj))
3751 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3752 self.assertEqual(text_type(obj_decoded), text_type(obj))
3753 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3754 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3755 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3757 obj_decoded.expl_llen,
3758 len(len_encode(len(obj_encoded))),
3760 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3761 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3764 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3766 self.assertEqual(obj_decoded.expl_offset, offset)
3767 assert_exceeding_data(
3769 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3773 evgens = list(obj_expled.decode_evgen(
3774 obj_expled_encoded + tail_junk,
3776 decode_path=decode_path,
3779 self.assertEqual(len(evgens), 1)
3780 _decode_path, obj, tail = evgens[0]
3781 self.assertSequenceEqual(tail, tail_junk)
3782 self.assertEqual(_decode_path, decode_path)
3783 if not getattr(self, "evgen_mode_skip_value", True):
3784 self.assertEqual(obj, obj_decoded)
3785 self.assertEqual(obj.expl_offset, offset)
3790 cyrillic_letters = text(
3791 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3797 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3798 base_klass = UTF8String
3800 @given(cyrillic_letters)
3801 def test_byte_per_primitive(self, chars):
3803 char_raw = char.encode("utf-8")
3804 encoded = b"".join((
3805 self.base_klass().tag_constructed,
3807 OctetString(char_raw[:1]).encode(),
3808 OctetString(char_raw[1:2]).encode(),
3812 self.base_klass().decod(encoded, ctx={"bered": True}),
3817 class UnicodeDecodeErrorMixin(object):
3818 @given(cyrillic_letters)
3819 def test_unicode_decode_error(self, cyrillic_text):
3820 with self.assertRaises(DecodeError):
3821 self.base_klass(cyrillic_text)
3824 class TestNumericString(StringMixin, CommonMixin, TestCase):
3825 base_klass = NumericString
3827 def text_alphabet(self):
3830 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3831 def test_non_numeric(self, non_numeric_text):
3832 with assertRaisesRegex(self, DecodeError, "non-numeric"):
3833 self.base_klass(non_numeric_text)
3836 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3837 integers(min_value=0),
3840 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3841 value, bound_min = list(sorted(ints))
3843 class String(self.base_klass):
3844 bounds = (bound_min, bound_min)
3845 with self.assertRaises(DecodeError) as err:
3847 self.base_klass(b"1" * value).encode(),
3849 decode_path=decode_path,
3852 self.assertEqual(err.exception.offset, offset)
3853 self.assertEqual(err.exception.decode_path, decode_path)
3855 def test_byte_per_primitive(self):
3856 encoded = b"".join((
3857 self.base_klass().tag_constructed,
3859 OctetString(b"1").encode(),
3860 OctetString(b"2").encode(),
3864 self.base_klass().decod(encoded, ctx={"bered": True}),
3869 class TestPrintableString(
3870 UnicodeDecodeErrorMixin,
3875 base_klass = PrintableString
3877 def text_alphabet(self):
3878 return ascii_letters + digits + " '()+,-./:=?"
3880 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3881 def test_non_printable(self, non_printable_text):
3882 with assertRaisesRegex(self, DecodeError, "non-printable"):
3883 self.base_klass(non_printable_text)
3886 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3887 integers(min_value=0),
3890 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3891 value, bound_min = list(sorted(ints))
3893 class String(self.base_klass):
3894 bounds = (bound_min, bound_min)
3895 with self.assertRaises(DecodeError) as err:
3897 self.base_klass(b"1" * value).encode(),
3899 decode_path=decode_path,
3902 self.assertEqual(err.exception.offset, offset)
3903 self.assertEqual(err.exception.decode_path, decode_path)
3905 def test_allowable_invalid_chars(self):
3907 ("*", {"allow_asterisk": True}),
3908 ("&", {"allow_ampersand": True}),
3909 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3912 obj = self.base_klass(s)
3913 for prop in kwargs.keys():
3914 self.assertFalse(getattr(obj, prop))
3916 with assertRaisesRegex(self, DecodeError, "non-printable"):
3918 self.base_klass(s, **kwargs)
3919 klass = self.base_klass(**kwargs)
3921 for prop in kwargs.keys():
3922 self.assertTrue(getattr(obj, prop))
3925 for prop in kwargs.keys():
3926 self.assertTrue(getattr(obj, prop))
3929 class TestTeletexString(
3930 UnicodeDecodeErrorMixin,
3935 base_klass = TeletexString
3938 class TestVideotexString(
3939 UnicodeDecodeErrorMixin,
3944 base_klass = VideotexString
3947 class TestIA5String(
3948 UnicodeDecodeErrorMixin,
3953 base_klass = IA5String
3956 class TestGraphicString(
3957 UnicodeDecodeErrorMixin,
3962 base_klass = GraphicString
3965 class TestVisibleString(
3966 UnicodeDecodeErrorMixin,
3971 base_klass = VisibleString
3973 def test_x690_vector(self):
3974 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3975 self.assertSequenceEqual(tail, b"")
3976 self.assertEqual(str(obj), "Jones")
3977 self.assertFalse(obj.ber_encoded)
3978 self.assertFalse(obj.lenindef)
3979 self.assertFalse(obj.bered)
3981 obj, tail = VisibleString().decode(
3982 hexdec("3A0904034A6F6E04026573"),
3983 ctx={"bered": True},
3985 self.assertSequenceEqual(tail, b"")
3986 self.assertEqual(str(obj), "Jones")
3987 self.assertTrue(obj.ber_encoded)
3988 self.assertFalse(obj.lenindef)
3989 self.assertTrue(obj.bered)
3991 self.assertTrue(obj.ber_encoded)
3992 self.assertFalse(obj.lenindef)
3993 self.assertTrue(obj.bered)
3995 obj, tail = VisibleString().decode(
3996 hexdec("3A8004034A6F6E040265730000"),
3997 ctx={"bered": True},
3999 self.assertSequenceEqual(tail, b"")
4000 self.assertEqual(str(obj), "Jones")
4001 self.assertTrue(obj.ber_encoded)
4002 self.assertTrue(obj.lenindef)
4003 self.assertTrue(obj.bered)
4005 self.assertTrue(obj.ber_encoded)
4006 self.assertTrue(obj.lenindef)
4007 self.assertTrue(obj.bered)
4010 class TestGeneralString(
4011 UnicodeDecodeErrorMixin,
4016 base_klass = GeneralString
4019 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4020 base_klass = UniversalString
4023 class TestBMPString(StringMixin, CommonMixin, TestCase):
4024 base_klass = BMPString
4028 def generalized_time_values_strategy(
4036 if draw(booleans()):
4037 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4039 value = value.replace(microsecond=0)
4041 if draw(booleans()):
4042 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4044 default = default.replace(microsecond=0)
4048 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4050 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4051 optional = draw(one_of(none(), booleans()))
4053 draw(integers(min_value=0)),
4054 draw(integers(min_value=0)),
4055 draw(integers(min_value=0)),
4057 return (value, impl, expl, default, optional, _decoded)
4060 class TimeMixin(object):
4061 def test_invalid_value_type(self):
4062 with self.assertRaises(InvalidValueType) as err:
4063 self.base_klass(datetime.now().timetuple())
4066 @given(data_strategy())
4067 def test_optional(self, d):
4068 default = d.draw(datetimes(
4069 min_value=self.min_datetime,
4070 max_value=self.max_datetime,
4072 optional = d.draw(booleans())
4073 obj = self.base_klass(default=default, optional=optional)
4074 self.assertTrue(obj.optional)
4076 @given(data_strategy())
4077 def test_ready(self, d):
4078 obj = self.base_klass()
4079 self.assertFalse(obj.ready)
4082 pprint(obj, big_blobs=True, with_decode_path=True)
4083 with self.assertRaises(ObjNotReady) as err:
4086 with self.assertRaises(ObjNotReady) as err:
4088 value = d.draw(datetimes(
4089 min_value=self.min_datetime,
4090 max_value=self.max_datetime,
4092 obj = self.base_klass(value)
4093 self.assertTrue(obj.ready)
4096 pprint(obj, big_blobs=True, with_decode_path=True)
4098 @given(data_strategy())
4099 def test_comparison(self, d):
4100 value1 = d.draw(datetimes(
4101 min_value=self.min_datetime,
4102 max_value=self.max_datetime,
4104 value2 = d.draw(datetimes(
4105 min_value=self.min_datetime,
4106 max_value=self.max_datetime,
4108 tag1 = d.draw(binary(min_size=1))
4109 tag2 = d.draw(binary(min_size=1))
4111 value1 = value1.replace(microsecond=0)
4112 value2 = value2.replace(microsecond=0)
4113 obj1 = self.base_klass(value1)
4114 obj2 = self.base_klass(value2)
4115 self.assertEqual(obj1 == obj2, value1 == value2)
4116 self.assertEqual(obj1 != obj2, value1 != value2)
4117 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4118 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4119 obj1 = self.base_klass(value1, impl=tag1)
4120 obj2 = self.base_klass(value1, impl=tag2)
4121 self.assertEqual(obj1 == obj2, tag1 == tag2)
4122 self.assertEqual(obj1 != obj2, tag1 != tag2)
4124 @given(data_strategy())
4125 def test_call(self, d):
4133 ) = d.draw(generalized_time_values_strategy(
4134 min_datetime=self.min_datetime,
4135 max_datetime=self.max_datetime,
4136 omit_ms=self.omit_ms,
4138 obj_initial = self.base_klass(
4139 value=value_initial,
4142 default=default_initial,
4143 optional=optional_initial or False,
4144 _decoded=_decoded_initial,
4153 ) = d.draw(generalized_time_values_strategy(
4154 min_datetime=self.min_datetime,
4155 max_datetime=self.max_datetime,
4156 omit_ms=self.omit_ms,
4157 do_expl=impl_initial is None,
4167 value_expected = default if value is None else value
4169 default_initial if value_expected is None
4172 self.assertEqual(obj, value_expected)
4173 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4174 self.assertEqual(obj.expl_tag, expl or expl_initial)
4177 default_initial if default is None else default,
4179 if obj.default is None:
4180 optional = optional_initial if optional is None else optional
4181 optional = False if optional is None else optional
4184 self.assertEqual(obj.optional, optional)
4186 @given(data_strategy())
4187 def test_copy(self, d):
4188 values = d.draw(generalized_time_values_strategy(
4189 min_datetime=self.min_datetime,
4190 max_datetime=self.max_datetime,
4192 obj = self.base_klass(*values)
4193 for copy_func in copy_funcs:
4194 obj_copied = copy_func(obj)
4195 self.assert_copied_basic_fields(obj, obj_copied)
4196 self.assertEqual(obj._value, obj_copied._value)
4198 @given(data_strategy())
4199 def test_stripped(self, d):
4200 value = d.draw(datetimes(
4201 min_value=self.min_datetime,
4202 max_value=self.max_datetime,
4204 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4205 obj = self.base_klass(value, impl=tag_impl)
4206 with self.assertRaises(NotEnoughData):
4207 obj.decode(obj.encode()[:-1])
4209 @given(data_strategy())
4210 def test_stripped_expl(self, d):
4211 value = d.draw(datetimes(
4212 min_value=self.min_datetime,
4213 max_value=self.max_datetime,
4215 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4216 obj = self.base_klass(value, expl=tag_expl)
4217 with self.assertRaises(NotEnoughData):
4218 obj.decode(obj.encode()[:-1])
4220 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4221 @given(data_strategy())
4222 def test_symmetric(self, d):
4223 values = d.draw(generalized_time_values_strategy(
4224 min_datetime=self.min_datetime,
4225 max_datetime=self.max_datetime,
4227 value = d.draw(datetimes(
4228 min_value=self.min_datetime,
4229 max_value=self.max_datetime,
4231 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4232 offset = d.draw(integers(min_value=0))
4233 tail_junk = d.draw(binary(max_size=5))
4234 _, _, _, default, optional, _decoded = values
4235 obj = self.base_klass(
4243 pprint(obj, big_blobs=True, with_decode_path=True)
4244 self.assertFalse(obj.expled)
4245 obj_encoded = obj.encode()
4246 self.assertEqual(encode2pass(obj), obj_encoded)
4247 self.additional_symmetric_check(value, obj_encoded)
4248 obj_expled = obj(value, expl=tag_expl)
4249 self.assertTrue(obj_expled.expled)
4251 list(obj_expled.pps())
4252 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4253 obj_expled_encoded = obj_expled.encode()
4254 ctx_copied = deepcopy(ctx_dummy)
4255 obj_decoded, tail = obj_expled.decode(
4256 obj_expled_encoded + tail_junk,
4260 self.assertDictEqual(ctx_copied, ctx_dummy)
4262 list(obj_decoded.pps())
4263 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4264 self.assertEqual(tail, tail_junk)
4265 self.assertEqual(obj_decoded, obj_expled)
4266 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4267 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4268 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4269 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4270 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4272 obj_decoded.expl_llen,
4273 len(len_encode(len(obj_encoded))),
4275 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4276 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4279 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4281 self.assertEqual(obj_decoded.expl_offset, offset)
4282 assert_exceeding_data(
4284 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4289 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4290 base_klass = GeneralizedTime
4292 min_datetime = datetime(1900, 1, 1)
4293 max_datetime = datetime(9999, 12, 31)
4294 evgen_mode_skip_value = False
4296 def additional_symmetric_check(self, value, obj_encoded):
4297 if value.microsecond > 0:
4298 self.assertFalse(obj_encoded.endswith(b"0Z"))
4300 def test_repr_not_ready(self):
4301 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4302 repr(GeneralizedTime())
4304 def test_x690_vector_valid(self):
4308 b"19920722132100.3Z",
4310 GeneralizedTime(data)
4312 def test_x690_vector_invalid(self):
4315 b"19920622123421.0Z",
4316 b"19920722132100.30Z",
4318 with self.assertRaises(DecodeError) as err:
4319 GeneralizedTime(data)
4322 def test_go_vectors_invalid(self):
4334 b"-20100102030410Z",
4335 b"2010-0102030410Z",
4336 b"2010-0002030410Z",
4337 b"201001-02030410Z",
4338 b"20100102-030410Z",
4339 b"2010010203-0410Z",
4340 b"201001020304-10Z",
4341 # These ones are INVALID in *DER*, but accepted
4342 # by Go's encoding/asn1
4343 b"20100102030405+0607",
4344 b"20100102030405-0607",
4346 with self.assertRaises(DecodeError) as err:
4347 GeneralizedTime(data)
4350 def test_go_vectors_valid(self):
4352 GeneralizedTime(b"20100102030405Z").todatetime(),
4353 datetime(2010, 1, 2, 3, 4, 5, 0),
4356 def test_go_vectors_valid_ber(self):
4358 b"20100102030405+0607",
4359 b"20100102030405-0607",
4361 GeneralizedTime(data, ctx={"bered": True})
4363 def test_utc_offsets(self):
4364 """Some know equal UTC offsets
4367 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4371 "200101011130-0700",
4372 "200101011500-03:30",
4375 self.assertEqual(dts[0], dts[1])
4376 self.assertEqual(dts[0], dts[2])
4377 self.assertEqual(dts[0], dts[3])
4379 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4380 @given(data_strategy())
4381 def test_valid_ber(self, d):
4382 min_year = 1901 if PY2 else 2
4383 year = d.draw(integers(min_value=min_year, max_value=9999))
4384 month = d.draw(integers(min_value=1, max_value=12))
4385 day = d.draw(integers(min_value=1, max_value=28))
4386 hours = d.draw(integers(min_value=0, max_value=23))
4387 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4388 dt = datetime(year, month, day, hours)
4389 fractions_sign = d.draw(sampled_from(" ,."))
4391 if fractions_sign != " ":
4392 fractions = random()
4393 if d.draw(booleans()):
4394 minutes = d.draw(integers(min_value=0, max_value=59))
4395 data += "%02d" % minutes
4396 dt += timedelta(seconds=60 * minutes)
4397 if d.draw(booleans()):
4398 seconds = d.draw(integers(min_value=0, max_value=59))
4399 data += "%02d" % seconds
4400 dt += timedelta(seconds=seconds)
4401 if fractions is not None:
4402 dt += timedelta(microseconds=10**6 * fractions)
4403 elif fractions is not None:
4404 dt += timedelta(seconds=60 * fractions)
4405 elif fractions is not None:
4406 dt += timedelta(seconds=3600 * fractions)
4407 if fractions is not None:
4408 data += fractions_sign + str(fractions)[2:]
4409 if d.draw(booleans()):
4411 elif d.draw(booleans()):
4412 offset_hour = d.draw(integers(min_value=0, max_value=13))
4414 if d.draw(booleans()):
4419 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4420 data += "%02d" % offset_hour
4421 minutes_separator = d.draw(sampled_from((None, "", ":")))
4422 if minutes_separator is not None:
4423 offset_minute = d.draw(integers(min_value=0, max_value=59))
4424 dt -= timedelta(seconds=sign * 60 * offset_minute)
4425 data += "%s%02d" % (minutes_separator, offset_minute)
4426 data = data.encode("ascii")
4427 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4429 GeneralizedTime().decod(data_der)
4434 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4437 mktime(obj.todatetime().timetuple()),
4438 mktime(dt.timetuple()),
4441 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4442 self.assertEqual(obj.ber_encoded, not dered)
4443 self.assertEqual(obj.bered, not dered)
4444 self.assertEqual(obj.ber_raw, None if dered else data)
4445 self.assertEqual(obj.encode() == data_der, dered)
4450 def test_invalid_ber(self):
4452 # "00010203040506.07",
4453 "-0010203040506.07",
4454 "0001-203040506.07",
4455 "000102-3040506.07",
4456 "00010203-40506.07",
4457 "0001020304-506.07",
4458 "000102030405-6.07",
4459 "00010203040506.-7",
4460 "+0010203040506.07",
4461 "0001+203040506.07",
4462 "000102+3040506.07",
4463 "00010203+40506.07",
4464 "0001020304+506.07",
4465 "000102030405+6.07",
4466 "00010203040506.+7",
4467 " 0010203040506.07",
4468 "0001 203040506.07",
4469 "000102 3040506.07",
4470 "00010203 40506.07",
4471 "0001020304 506.07",
4472 "000102030405 6.07",
4473 "00010203040506. 7",
4474 "001 0203040506.07",
4475 "00012 03040506.07",
4476 "0001023 040506.07",
4477 "000102034 0506.07",
4478 "00010203045 06.07",
4479 "0001020304056 .07",
4480 "00010203040506.7 ",
4560 "00010203040506.07+15",
4561 "00010203040506.07-15",
4562 "00010203040506.07+14:60",
4563 "00010203040506.07+1460",
4564 "00010203040506.07-1460",
4565 "00010203040506.07+00:60",
4566 "00010203040506.07-00:60",
4568 "00010203040506+15",
4569 "00010203040506-15",
4570 "00010203040506+14:60",
4571 "00010203040506+1460",
4572 "00010203040506-1460",
4573 "00010203040506+00:60",
4574 "00010203040506-00:60",
4583 with self.assertRaises(DecodeError):
4584 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4585 data = data.replace(".", ",")
4586 with self.assertRaises(DecodeError):
4587 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4591 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4592 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4594 binary(min_size=1, max_size=1),
4596 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4597 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4600 def test_junk(self, part0, part1, part2):
4601 junk = part0 + part1 + part2
4602 assume(not (set(junk) <= set(digits.encode("ascii"))))
4603 with self.assertRaises(DecodeError):
4604 GeneralizedTime().decode(
4605 GeneralizedTime.tag_default +
4606 len_encode(len(junk)) +
4612 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4613 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4615 binary(min_size=1, max_size=1),
4617 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4618 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4621 def test_junk_dm(self, part0, part1, part2):
4622 junk = part0 + part1 + part2
4623 assume(not (set(junk) <= set(digits.encode("ascii"))))
4624 with self.assertRaises(DecodeError):
4625 GeneralizedTime().decode(
4626 GeneralizedTime.tag_default +
4627 len_encode(len(junk)) +
4631 def test_ns_fractions(self):
4632 GeneralizedTime(b"20010101000000.000001Z")
4633 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4634 GeneralizedTime(b"20010101000000.0000001Z")
4636 def test_non_pure_integers(self):
4638 # b"20000102030405Z,
4645 b"20000102030405.+6Z",
4646 b"20000102030405.-6Z",
4653 b"20000102030405._6Z",
4654 b"20000102030405.6_Z",
4661 b"20000102030405. 6Z",
4668 b"20000102030405.6 Z",
4670 with self.assertRaises(DecodeError):
4671 GeneralizedTime(data)
4674 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4675 base_klass = UTCTime
4677 min_datetime = datetime(2000, 1, 1)
4678 max_datetime = datetime(2049, 12, 31)
4679 evgen_mode_skip_value = False
4681 def additional_symmetric_check(self, value, obj_encoded):
4684 def test_repr_not_ready(self):
4685 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4688 def test_x690_vector_valid(self):
4696 def test_x690_vector_invalid(self):
4701 with self.assertRaises(DecodeError) as err:
4705 def test_go_vectors_invalid(self):
4731 # These ones are INVALID in *DER*, but accepted
4732 # by Go's encoding/asn1
4733 b"910506164540-0700",
4734 b"910506164540+0730",
4738 with self.assertRaises(DecodeError) as err:
4742 def test_go_vectors_valid(self):
4744 UTCTime(b"910506234540Z").todatetime(),
4745 datetime(1991, 5, 6, 23, 45, 40, 0),
4748 def test_non_pure_integers(self):
4777 with self.assertRaises(DecodeError):
4780 def test_x680_vector_valid_ber(self):
4782 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4783 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4784 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4785 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4787 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4788 obj = UTCTime().decod(data_der, ctx={"bered": True})
4789 self.assertEqual(obj, dt)
4790 self.assertEqual(obj.todatetime(), dt)
4791 self.assertTrue(obj.ber_encoded)
4792 self.assertTrue(obj.bered)
4793 self.assertEqual(obj.ber_raw, data)
4794 self.assertNotEqual(obj.encode(), data_der)
4797 def test_go_vectors_valid_ber(self):
4799 b"910506164540-0700",
4800 b"910506164540+0730",
4804 data = UTCTime.tag_default + len_encode(len(data)) + data
4805 obj = UTCTime().decod(data, ctx={"bered": True})
4806 self.assertTrue(obj.ber_encoded)
4807 self.assertTrue(obj.bered)
4808 self.assertNotEqual(obj.encode(), data)
4811 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4812 @given(data_strategy())
4813 def test_valid_ber(self, d):
4814 year = d.draw(integers(min_value=0, max_value=99))
4815 month = d.draw(integers(min_value=1, max_value=12))
4816 day = d.draw(integers(min_value=1, max_value=28))
4817 hours = d.draw(integers(min_value=0, max_value=23))
4818 minute = d.draw(integers(min_value=0, max_value=59))
4819 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4821 year + (2000 if year < 50 else 1900),
4828 if d.draw(booleans()):
4830 seconds = d.draw(integers(min_value=0, max_value=59))
4831 data += "%02d" % seconds
4832 dt += timedelta(seconds=seconds)
4833 if d.draw(booleans()):
4837 offset_hour = d.draw(integers(min_value=0, max_value=13))
4838 offset_minute = d.draw(integers(min_value=0, max_value=59))
4839 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4840 if d.draw(booleans()):
4846 data += "%02d%02d" % (offset_hour, offset_minute)
4847 data = data.encode("ascii")
4848 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4849 obj = UTCTime().decod(data_der, ctx={"bered": True})
4850 self.assertEqual(obj, dt)
4851 self.assertEqual(obj.todatetime(), dt)
4852 self.assertEqual(obj.ber_encoded, not dered)
4853 self.assertEqual(obj.bered, not dered)
4854 self.assertEqual(obj.ber_raw, None if dered else data)
4855 self.assertEqual(obj.encode() == data_der, dered)
4860 def test_invalid_ber(self):
4901 b"0001020304+0000Z",
4910 with self.assertRaises(DecodeError):
4911 UTCTime(data, ctx={"bered": True})
4912 data = data[:8] + data[8+2:]
4913 with self.assertRaises(DecodeError):
4914 UTCTime(data, ctx={"bered": True})
4959 b"000102030405+000",
4960 b"000102030405+000Z",
4961 b"000102030405+0000Z",
4962 b"000102030405+-101",
4963 b"000102030405+01-1",
4964 b"000102030405+0060",
4965 b"000102030405+1401",
4966 b"500101000002+0003",
4968 with self.assertRaises(DecodeError):
4969 UTCTime(data, ctx={"bered": True})
4971 @given(integers(min_value=0, max_value=49))
4972 def test_pre50(self, year):
4974 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4978 @given(integers(min_value=50, max_value=99))
4979 def test_post50(self, year):
4981 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4987 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4988 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4990 binary(min_size=1, max_size=1),
4992 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4993 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4996 def test_junk(self, part0, part1, part2):
4997 junk = part0 + part1 + part2
4998 assume(not (set(junk) <= set(digits.encode("ascii"))))
4999 with self.assertRaises(DecodeError):
5001 UTCTime.tag_default +
5002 len_encode(len(junk)) +
5008 def tlv_value_strategy(draw):
5009 tag_num = draw(integers(min_value=1))
5010 data = draw(binary())
5011 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5015 def any_values_strategy(draw, do_expl=False):
5016 value = draw(one_of(none(), tlv_value_strategy()))
5019 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5020 optional = draw(one_of(none(), booleans()))
5022 draw(integers(min_value=0)),
5023 draw(integers(min_value=0)),
5024 draw(integers(min_value=0)),
5026 return (value, expl, optional, _decoded)
5029 class AnyInherited(Any):
5033 class TestAny(CommonMixin, TestCase):
5036 def test_invalid_value_type(self):
5037 with self.assertRaises(InvalidValueType) as err:
5042 def test_optional(self, optional):
5043 obj = Any(optional=optional)
5044 self.assertEqual(obj.optional, optional)
5046 @given(tlv_value_strategy())
5047 def test_ready(self, value):
5049 self.assertFalse(obj.ready)
5052 pprint(obj, big_blobs=True, with_decode_path=True)
5053 with self.assertRaises(ObjNotReady) as err:
5056 with self.assertRaises(ObjNotReady) as err:
5059 self.assertTrue(obj.ready)
5062 pprint(obj, big_blobs=True, with_decode_path=True)
5065 def test_basic(self, value):
5066 integer_encoded = Integer(value).encode()
5068 Any(integer_encoded),
5069 Any(Integer(value)),
5070 Any(Any(Integer(value))),
5072 self.assertSequenceEqual(bytes(obj), integer_encoded)
5074 obj.decode(obj.encode())[0].vlen,
5075 len(integer_encoded),
5079 pprint(obj, big_blobs=True, with_decode_path=True)
5080 self.assertSequenceEqual(obj.encode(), integer_encoded)
5082 @given(tlv_value_strategy(), tlv_value_strategy())
5083 def test_comparison(self, value1, value2):
5084 for klass in (Any, AnyInherited):
5085 obj1 = klass(value1)
5086 obj2 = klass(value2)
5087 self.assertEqual(obj1 == obj2, value1 == value2)
5088 self.assertEqual(obj1 != obj2, value1 != value2)
5089 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5091 @given(data_strategy())
5092 def test_call(self, d):
5093 for klass in (Any, AnyInherited):
5099 ) = d.draw(any_values_strategy())
5100 obj_initial = klass(
5103 optional_initial or False,
5111 ) = d.draw(any_values_strategy(do_expl=True))
5112 obj = obj_initial(value, expl, optional)
5114 value_expected = None if value is None else value
5115 self.assertEqual(obj, value_expected)
5116 self.assertEqual(obj.expl_tag, expl or expl_initial)
5117 if obj.default is None:
5118 optional = optional_initial if optional is None else optional
5119 optional = False if optional is None else optional
5120 self.assertEqual(obj.optional, optional)
5122 def test_simultaneous_impl_expl(self):
5123 # override it, as Any does not have implicit tag
5126 def test_decoded(self):
5127 # override it, as Any does not have implicit tag
5130 @given(any_values_strategy())
5131 def test_copy(self, values):
5132 for klass in (Any, AnyInherited):
5133 obj = klass(*values)
5134 for copy_func in copy_funcs:
5135 obj_copied = copy_func(obj)
5136 self.assert_copied_basic_fields(obj, obj_copied)
5137 self.assertEqual(obj._value, obj_copied._value)
5139 @given(binary().map(OctetString))
5140 def test_stripped(self, value):
5142 with self.assertRaises(NotEnoughData):
5143 obj.decode(obj.encode()[:-1])
5146 tlv_value_strategy(),
5147 integers(min_value=1).map(tag_ctxc),
5149 def test_stripped_expl(self, value, tag_expl):
5150 obj = Any(value, expl=tag_expl)
5151 with self.assertRaises(NotEnoughData):
5152 obj.decode(obj.encode()[:-1])
5155 integers(min_value=31),
5156 integers(min_value=0),
5159 def test_bad_tag(self, tag, offset, decode_path):
5160 with self.assertRaises(DecodeError) as err:
5162 tag_encode(tag)[:-1],
5164 decode_path=decode_path,
5167 self.assertEqual(err.exception.offset, offset)
5168 self.assertEqual(err.exception.decode_path, decode_path)
5171 integers(min_value=128),
5172 integers(min_value=0),
5175 def test_bad_len(self, l, offset, decode_path):
5176 with self.assertRaises(DecodeError) as err:
5178 Any.tag_default + len_encode(l)[:-1],
5180 decode_path=decode_path,
5183 self.assertEqual(err.exception.offset, offset)
5184 self.assertEqual(err.exception.decode_path, decode_path)
5186 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5188 any_values_strategy(),
5189 integers().map(lambda x: Integer(x).encode()),
5190 integers(min_value=1).map(tag_ctxc),
5191 integers(min_value=0),
5195 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5196 for klass in (Any, AnyInherited):
5197 _, _, optional, _decoded = values
5198 obj = klass(value=value, optional=optional, _decoded=_decoded)
5201 pprint(obj, big_blobs=True, with_decode_path=True)
5202 self.assertFalse(obj.expled)
5203 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5204 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5205 obj_encoded = obj.encode()
5206 self.assertEqual(encode2pass(obj), obj_encoded)
5207 obj_expled = obj(value, expl=tag_expl)
5208 self.assertTrue(obj_expled.expled)
5209 tag_class, _, tag_num = tag_decode(tag_expl)
5210 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5212 list(obj_expled.pps())
5213 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5214 obj_expled_encoded = obj_expled.encode()
5215 ctx_copied = deepcopy(ctx_dummy)
5216 obj_decoded, tail = obj_expled.decode(
5217 obj_expled_encoded + tail_junk,
5221 self.assertDictEqual(ctx_copied, ctx_dummy)
5223 list(obj_decoded.pps())
5224 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5225 self.assertEqual(tail, tail_junk)
5226 self.assertEqual(obj_decoded, obj_expled)
5227 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5228 self.assertEqual(bytes(obj_decoded), bytes(obj))
5229 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5230 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5231 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5233 obj_decoded.expl_llen,
5234 len(len_encode(len(obj_encoded))),
5236 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5237 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5240 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5242 self.assertEqual(obj_decoded.expl_offset, offset)
5243 self.assertEqual(obj_decoded.tlen, 0)
5244 self.assertEqual(obj_decoded.llen, 0)
5245 self.assertEqual(obj_decoded.vlen, len(value))
5246 assert_exceeding_data(
5248 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5252 evgens = list(obj_expled.decode_evgen(
5253 obj_expled_encoded + tail_junk,
5255 decode_path=decode_path,
5258 self.assertEqual(len(evgens), 1)
5259 _decode_path, obj, tail = evgens[0]
5260 self.assertSequenceEqual(tail, tail_junk)
5261 self.assertEqual(_decode_path, decode_path)
5262 self.assertEqual(obj.expl_offset, offset)
5267 integers(min_value=1).map(tag_ctxc),
5268 integers(min_value=0, max_value=3),
5269 integers(min_value=0),
5273 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5274 chunk = Boolean(False, expl=expl).encode()
5276 OctetString.tag_default +
5278 b"".join([chunk] * chunks) +
5281 with self.assertRaises(LenIndefForm):
5285 decode_path=decode_path,
5287 obj, tail = Any().decode(
5290 decode_path=decode_path,
5291 ctx={"bered": True},
5293 self.assertSequenceEqual(tail, junk)
5294 self.assertEqual(obj.offset, offset)
5295 self.assertEqual(obj.tlvlen, len(encoded))
5296 self.assertTrue(obj.lenindef)
5297 self.assertFalse(obj.ber_encoded)
5298 self.assertTrue(obj.bered)
5300 self.assertTrue(obj.lenindef)
5301 self.assertFalse(obj.ber_encoded)
5302 self.assertTrue(obj.bered)
5305 pprint(obj, big_blobs=True, with_decode_path=True)
5306 with self.assertRaises(NotEnoughData) as err:
5310 decode_path=decode_path,
5311 ctx={"bered": True},
5313 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5314 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5316 class SeqOf(SequenceOf):
5317 schema = Boolean(expl=expl)
5319 class Seq(Sequence):
5321 ("type", ObjectIdentifier(defines=((("value",), {
5322 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5327 ("type", ObjectIdentifier("1.2.3")),
5328 ("value", Any(encoded)),
5330 seq_encoded = seq.encode()
5331 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5332 self.assertIsNotNone(seq_decoded["value"].defined)
5334 list(seq_decoded.pps())
5335 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5336 self.assertTrue(seq_decoded.bered)
5337 self.assertFalse(seq_decoded["type"].bered)
5338 self.assertTrue(seq_decoded["value"].bered)
5340 chunk = chunk[:-1] + b"\x01"
5341 chunks = b"".join([chunk] * (chunks + 1))
5342 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5344 ("type", ObjectIdentifier("1.2.3")),
5345 ("value", Any(encoded)),
5347 seq_encoded = seq.encode()
5348 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5349 self.assertIsNotNone(seq_decoded["value"].defined)
5351 list(seq_decoded.pps())
5352 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5353 self.assertTrue(seq_decoded.bered)
5354 self.assertFalse(seq_decoded["type"].bered)
5355 self.assertTrue(seq_decoded["value"].bered)
5359 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5361 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5362 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5364 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5365 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5367 min_size=len(names),
5368 max_size=len(names),
5371 (name, Integer(**tag_kwargs))
5372 for name, tag_kwargs in zip(names, tags)
5375 if value_required or draw(booleans()):
5376 value = draw(tuples(
5377 sampled_from([name for name, _ in schema]),
5378 integers().map(Integer),
5382 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5383 default = draw(one_of(
5385 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5387 optional = draw(one_of(none(), booleans()))
5389 draw(integers(min_value=0)),
5390 draw(integers(min_value=0)),
5391 draw(integers(min_value=0)),
5393 return (schema, value, expl, default, optional, _decoded)
5396 class ChoiceInherited(Choice):
5400 class TestChoice(CommonMixin, TestCase):
5402 schema = (("whatever", Boolean()),)
5405 def test_schema_required(self):
5406 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5409 def test_impl_forbidden(self):
5410 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5411 Choice(impl=b"whatever")
5413 def test_invalid_value_type(self):
5414 with self.assertRaises(InvalidValueType) as err:
5415 self.base_klass(123)
5417 with self.assertRaises(ObjUnknown) as err:
5418 self.base_klass(("whenever", Boolean(False)))
5420 with self.assertRaises(InvalidValueType) as err:
5421 self.base_klass(("whatever", Integer(123)))
5425 def test_optional(self, optional):
5426 obj = self.base_klass(
5427 default=self.base_klass(("whatever", Boolean(False))),
5430 self.assertTrue(obj.optional)
5433 def test_ready(self, value):
5434 obj = self.base_klass()
5435 self.assertFalse(obj.ready)
5438 pprint(obj, big_blobs=True, with_decode_path=True)
5439 self.assertIsNone(obj["whatever"])
5440 with self.assertRaises(ObjNotReady) as err:
5443 with self.assertRaises(ObjNotReady) as err:
5445 obj["whatever"] = Boolean()
5446 self.assertFalse(obj.ready)
5449 pprint(obj, big_blobs=True, with_decode_path=True)
5450 obj["whatever"] = Boolean(value)
5451 self.assertTrue(obj.ready)
5454 pprint(obj, big_blobs=True, with_decode_path=True)
5456 @given(booleans(), booleans())
5457 def test_comparison(self, value1, value2):
5458 class WahlInherited(self.base_klass):
5460 for klass in (self.base_klass, WahlInherited):
5461 obj1 = klass(("whatever", Boolean(value1)))
5462 obj2 = klass(("whatever", Boolean(value2)))
5463 self.assertEqual(obj1 == obj2, value1 == value2)
5464 self.assertEqual(obj1 != obj2, value1 != value2)
5465 self.assertEqual(obj1 == obj2._value, value1 == value2)
5466 self.assertFalse(obj1 == obj2._value[1])
5468 @given(data_strategy())
5469 def test_call(self, d):
5470 for klass in (Choice, ChoiceInherited):
5478 ) = d.draw(choice_values_strategy())
5481 schema = schema_initial
5483 value=value_initial,
5485 default=default_initial,
5486 optional=optional_initial or False,
5487 _decoded=_decoded_initial,
5496 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5497 obj = obj_initial(value, expl, default, optional)
5499 value_expected = default if value is None else value
5501 default_initial if value_expected is None
5504 self.assertEqual(obj.choice, value_expected[0])
5505 self.assertEqual(obj.value, int(value_expected[1]))
5506 self.assertEqual(obj.expl_tag, expl or expl_initial)
5507 default_expect = default_initial if default is None else default
5508 if default_expect is not None:
5509 self.assertEqual(obj.default.choice, default_expect[0])
5510 self.assertEqual(obj.default.value, int(default_expect[1]))
5511 if obj.default is None:
5512 optional = optional_initial if optional is None else optional
5513 optional = False if optional is None else optional
5516 self.assertEqual(obj.optional, optional)
5517 self.assertEqual(obj.specs, obj_initial.specs)
5519 def test_simultaneous_impl_expl(self):
5520 # override it, as Any does not have implicit tag
5523 def test_decoded(self):
5524 # override it, as Any does not have implicit tag
5527 @given(choice_values_strategy())
5528 def test_copy(self, values):
5529 _schema, value, expl, default, optional, _decoded = values
5531 class Wahl(self.base_klass):
5533 register_class(Wahl)
5538 optional=optional or False,
5541 for copy_func in copy_funcs:
5542 obj_copied = copy_func(obj)
5543 self.assertIsNone(obj.tag)
5544 self.assertIsNone(obj_copied.tag)
5545 # hack for assert_copied_basic_fields
5546 obj.tag = "whatever"
5547 obj_copied.tag = "whatever"
5548 self.assert_copied_basic_fields(obj, obj_copied)
5550 self.assertEqual(obj._value, obj_copied._value)
5551 self.assertEqual(obj.specs, obj_copied.specs)
5554 def test_stripped(self, value):
5555 obj = self.base_klass(("whatever", Boolean(value)))
5556 with self.assertRaises(NotEnoughData):
5557 obj.decode(obj.encode()[:-1])
5561 integers(min_value=1).map(tag_ctxc),
5563 def test_stripped_expl(self, value, tag_expl):
5564 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5565 with self.assertRaises(NotEnoughData):
5566 obj.decode(obj.encode()[:-1])
5568 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5569 @given(data_strategy())
5570 def test_symmetric(self, d):
5571 _schema, value, _, default, optional, _decoded = d.draw(
5572 choice_values_strategy(value_required=True)
5574 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5575 offset = d.draw(integers(min_value=0))
5576 tail_junk = d.draw(binary(max_size=5))
5577 decode_path = d.draw(decode_path_strat)
5579 class Wahl(self.base_klass):
5589 pprint(obj, big_blobs=True, with_decode_path=True)
5590 self.assertFalse(obj.expled)
5591 self.assertEqual(obj.tag_order, obj.value.tag_order)
5592 obj_encoded = obj.encode()
5593 self.assertEqual(encode2pass(obj), obj_encoded)
5594 obj_expled = obj(value, expl=tag_expl)
5595 self.assertTrue(obj_expled.expled)
5596 tag_class, _, tag_num = tag_decode(tag_expl)
5597 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5599 list(obj_expled.pps())
5600 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5601 obj_expled_encoded = obj_expled.encode()
5602 ctx_copied = deepcopy(ctx_dummy)
5603 obj_decoded, tail = obj_expled.decode(
5604 obj_expled_encoded + tail_junk,
5608 self.assertDictEqual(ctx_copied, ctx_dummy)
5610 list(obj_decoded.pps())
5611 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5612 self.assertEqual(tail, tail_junk)
5613 self.assertEqual(obj_decoded, obj_expled)
5614 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5615 self.assertEqual(obj_decoded.value, obj_expled.value)
5616 self.assertEqual(obj_decoded.choice, obj.choice)
5617 self.assertEqual(obj_decoded.value, obj.value)
5618 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5619 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5620 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5622 obj_decoded.expl_llen,
5623 len(len_encode(len(obj_encoded))),
5625 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5626 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5629 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5631 self.assertEqual(obj_decoded.expl_offset, offset)
5632 self.assertSequenceEqual(
5634 obj_decoded.value.fulloffset - offset:
5635 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5639 assert_exceeding_data(
5641 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5645 evgens = list(obj_expled.decode_evgen(
5646 obj_expled_encoded + tail_junk,
5648 decode_path=decode_path,
5651 self.assertEqual(len(evgens), 2)
5652 _decode_path, obj, tail = evgens[0]
5653 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5654 _decode_path, obj, tail = evgens[1]
5655 self.assertSequenceEqual(tail, tail_junk)
5656 self.assertEqual(_decode_path, decode_path)
5657 self.assertEqual(obj.expl_offset, offset)
5662 def test_set_get(self, value):
5665 ("erste", Boolean()),
5666 ("zweite", Integer()),
5669 with self.assertRaises(ObjUnknown) as err:
5670 obj["whatever"] = "whenever"
5671 with self.assertRaises(InvalidValueType) as err:
5672 obj["zweite"] = Boolean(False)
5673 obj["zweite"] = Integer(value)
5675 with self.assertRaises(ObjUnknown) as err:
5678 self.assertIsNone(obj["erste"])
5679 self.assertEqual(obj["zweite"], Integer(value))
5681 def test_tag_mismatch(self):
5684 ("erste", Boolean()),
5686 int_encoded = Integer(123).encode()
5687 bool_encoded = Boolean(False).encode()
5689 obj.decode(bool_encoded)
5690 with self.assertRaises(TagMismatch):
5691 obj.decode(int_encoded)
5693 def test_tag_mismatch_underlying(self):
5694 class SeqOfBoolean(SequenceOf):
5697 class SeqOfInteger(SequenceOf):
5702 ("erste", SeqOfBoolean()),
5705 int_encoded = SeqOfInteger((Integer(123),)).encode()
5706 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5708 obj.decode(bool_encoded)
5709 with self.assertRaises(TagMismatch) as err:
5710 obj.decode(int_encoded)
5711 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5715 def seq_values_strategy(draw, seq_klass, do_expl=False):
5717 if draw(booleans()):
5719 value._value = draw(dictionaries(
5722 booleans().map(Boolean),
5723 integers().map(Integer),
5727 if draw(booleans()):
5728 schema = list(draw(dictionaries(
5731 booleans().map(Boolean),
5732 integers().map(Integer),
5738 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5740 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5742 if draw(booleans()):
5743 default = seq_klass()
5744 default._value = draw(dictionaries(
5747 booleans().map(Boolean),
5748 integers().map(Integer),
5751 optional = draw(one_of(none(), booleans()))
5753 draw(integers(min_value=0)),
5754 draw(integers(min_value=0)),
5755 draw(integers(min_value=0)),
5757 return (value, schema, impl, expl, default, optional, _decoded)
5761 def sequence_strategy(draw, seq_klass):
5762 inputs = draw(lists(
5764 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5765 tuples(just(Integer), integers(), one_of(none(), integers())),
5770 integers(min_value=1),
5771 min_size=len(inputs),
5772 max_size=len(inputs),
5775 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5776 for tag, expled in zip(tags, draw(lists(
5778 min_size=len(inputs),
5779 max_size=len(inputs),
5783 for i, optional in enumerate(draw(lists(
5784 sampled_from(("required", "optional", "empty")),
5785 min_size=len(inputs),
5786 max_size=len(inputs),
5788 if optional in ("optional", "empty"):
5789 inits[i]["optional"] = True
5790 if optional == "empty":
5792 empties = set(empties)
5793 names = list(draw(sets(
5795 min_size=len(inputs),
5796 max_size=len(inputs),
5799 for i, (klass, value, default) in enumerate(inputs):
5800 schema.append((names[i], klass(default=default, **inits[i])))
5801 seq_name = draw(text_letters())
5802 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5805 for i, (klass, value, default) in enumerate(inputs):
5812 "default_value": None if spec.default is None else default,
5816 expect["optional"] = True
5818 expect["presented"] = True
5819 expect["value"] = value
5821 expect["optional"] = True
5822 if default is not None and default == value:
5823 expect["presented"] = False
5824 seq[name] = klass(value)
5825 expects.append(expect)
5830 def sequences_strategy(draw, seq_klass):
5831 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5833 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5834 for tag, expled in zip(tags, draw(lists(
5841 i for i, is_default in enumerate(draw(lists(
5847 names = list(draw(sets(
5852 seq_expectses = draw(lists(
5853 sequence_strategy(seq_klass=seq_klass),
5857 seqs = [seq for seq, _ in seq_expectses]
5859 for i, (name, seq) in enumerate(zip(names, seqs)):
5862 seq(default=(seq if i in defaulted else None), **inits[i]),
5864 seq_name = draw(text_letters())
5865 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5868 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5871 "expects": expects_inner,
5874 seq_outer[name] = seq_inner
5875 if seq_outer.specs[name].default is None:
5876 expect["presented"] = True
5877 expect_outers.append(expect)
5878 return seq_outer, expect_outers
5881 class SeqMixing(object):
5882 def test_invalid_value_type(self):
5883 with self.assertRaises(InvalidValueType) as err:
5884 self.base_klass(123)
5887 def test_invalid_value_type_set(self):
5888 class Seq(self.base_klass):
5889 schema = (("whatever", Boolean()),)
5891 with self.assertRaises(InvalidValueType) as err:
5892 seq["whatever"] = Integer(123)
5896 def test_optional(self, optional):
5897 obj = self.base_klass(default=self.base_klass(), optional=optional)
5898 self.assertTrue(obj.optional)
5900 @given(data_strategy())
5901 def test_ready(self, d):
5903 str(i): v for i, v in enumerate(d.draw(lists(
5910 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5917 for name in d.draw(permutations(
5918 list(ready.keys()) + list(non_ready.keys()),
5920 schema_input.append((name, Boolean()))
5922 class Seq(self.base_klass):
5923 schema = tuple(schema_input)
5925 for name in ready.keys():
5927 seq[name] = Boolean()
5928 self.assertFalse(seq.ready)
5931 pprint(seq, big_blobs=True, with_decode_path=True)
5932 for name, value in ready.items():
5933 seq[name] = Boolean(value)
5934 self.assertFalse(seq.ready)
5937 pprint(seq, big_blobs=True, with_decode_path=True)
5938 with self.assertRaises(ObjNotReady) as err:
5941 with self.assertRaises(ObjNotReady) as err:
5943 for name, value in non_ready.items():
5944 seq[name] = Boolean(value)
5945 self.assertTrue(seq.ready)
5948 pprint(seq, big_blobs=True, with_decode_path=True)
5950 @given(data_strategy())
5951 def test_call(self, d):
5952 class SeqInherited(self.base_klass):
5954 for klass in (self.base_klass, SeqInherited):
5963 ) = d.draw(seq_values_strategy(seq_klass=klass))
5964 obj_initial = klass(
5970 optional_initial or False,
5981 ) = d.draw(seq_values_strategy(
5983 do_expl=impl_initial is None,
5985 obj = obj_initial(value, impl, expl, default, optional)
5986 value_expected = default if value is None else value
5988 default_initial if value_expected is None
5991 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
5992 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
5993 self.assertEqual(obj.expl_tag, expl or expl_initial)
5995 {} if obj.default is None else obj.default._value,
5996 getattr(default_initial if default is None else default, "_value", {}),
5998 if obj.default is None:
5999 optional = optional_initial if optional is None else optional
6000 optional = False if optional is None else optional
6003 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6004 self.assertEqual(obj.optional, optional)
6006 @given(data_strategy())
6007 def test_copy(self, d):
6008 class SeqInherited(self.base_klass):
6010 register_class(SeqInherited)
6011 for klass in (self.base_klass, SeqInherited):
6012 values = d.draw(seq_values_strategy(seq_klass=klass))
6013 obj = klass(*values)
6014 for copy_func in copy_funcs:
6015 obj_copied = copy_func(obj)
6016 self.assert_copied_basic_fields(obj, obj_copied)
6017 self.assertEqual(obj.specs, obj_copied.specs)
6018 self.assertEqual(obj._value, obj_copied._value)
6020 @given(data_strategy())
6021 def test_stripped(self, d):
6022 value = d.draw(integers())
6023 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6025 class Seq(self.base_klass):
6027 schema = (("whatever", Integer()),)
6029 seq["whatever"] = Integer(value)
6030 with self.assertRaises(NotEnoughData):
6031 seq.decode(seq.encode()[:-1])
6033 @given(data_strategy())
6034 def test_stripped_expl(self, d):
6035 value = d.draw(integers())
6036 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6038 class Seq(self.base_klass):
6040 schema = (("whatever", Integer()),)
6042 seq["whatever"] = Integer(value)
6043 with self.assertRaises(NotEnoughData):
6044 seq.decode(seq.encode()[:-1])
6046 @given(integers(min_value=3), binary(min_size=2))
6047 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6048 junk = tag_encode(junk_tag_num) + junk
6050 _, _, len_encoded = tag_strip(memoryview(junk))
6051 len_decode(len_encoded)
6057 class Seq(self.base_klass):
6059 ("whatever", Integer()),
6061 ("whenever", Integer()),
6064 seq["whatever"] = Integer(123)
6065 seq["junk"] = Any(junk)
6066 seq["whenever"] = Integer(123)
6067 with self.assertRaises(DecodeError):
6068 seq.decode(seq.encode())
6071 integers(min_value=31),
6072 integers(min_value=0),
6075 def test_bad_tag(self, tag, offset, decode_path):
6076 with self.assertRaises(DecodeError) as err:
6077 self.base_klass().decode(
6078 tag_encode(tag)[:-1],
6080 decode_path=decode_path,
6083 self.assertEqual(err.exception.offset, offset)
6084 self.assertEqual(err.exception.decode_path, decode_path)
6087 integers(min_value=128),
6088 integers(min_value=0),
6091 def test_bad_len(self, l, offset, decode_path):
6092 with self.assertRaises(DecodeError) as err:
6093 self.base_klass().decode(
6094 self.base_klass.tag_default + len_encode(l)[:-1],
6096 decode_path=decode_path,
6099 self.assertEqual(err.exception.offset, offset)
6100 self.assertEqual(err.exception.decode_path, decode_path)
6102 def _assert_expects(self, seq, expects):
6103 for expect in expects:
6105 seq.specs[expect["name"]].optional,
6108 if expect["default_value"] is not None:
6110 seq.specs[expect["name"]].default,
6111 expect["default_value"],
6113 if expect["presented"]:
6114 self.assertIn(expect["name"], seq)
6115 self.assertEqual(seq[expect["name"]], expect["value"])
6117 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6118 @given(data_strategy())
6119 def test_symmetric(self, d):
6120 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6121 tail_junk = d.draw(binary(max_size=5))
6122 decode_path = d.draw(decode_path_strat)
6123 self.assertTrue(seq.ready)
6124 self.assertFalse(seq.decoded)
6125 self._assert_expects(seq, expects)
6128 pprint(seq, big_blobs=True, with_decode_path=True)
6129 self.assertTrue(seq.ready)
6130 seq_encoded = seq.encode()
6131 self.assertEqual(encode2pass(seq), seq_encoded)
6132 seq_encoded_cer = encode_cer(seq)
6133 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6134 self.assertSequenceEqual(
6135 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6138 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6139 self.assertFalse(seq_decoded.lenindef)
6140 self.assertFalse(seq_decoded.ber_encoded)
6141 self.assertFalse(seq_decoded.bered)
6143 t, _, lv = tag_strip(seq_encoded)
6144 _, _, v = len_decode(lv)
6145 seq_encoded_lenindef = t + LENINDEF + v + EOC
6146 with self.assertRaises(DecodeError):
6147 seq.decode(seq_encoded_lenindef)
6148 ctx_copied = deepcopy(ctx_dummy)
6149 ctx_copied["bered"] = True
6150 seq_decoded_lenindef, tail_lenindef = seq.decode(
6151 seq_encoded_lenindef + tail_junk,
6154 del ctx_copied["bered"]
6155 self.assertDictEqual(ctx_copied, ctx_dummy)
6156 self.assertTrue(seq_decoded_lenindef.lenindef)
6157 self.assertTrue(seq_decoded_lenindef.bered)
6158 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6159 self.assertTrue(seq_decoded_lenindef.lenindef)
6160 self.assertTrue(seq_decoded_lenindef.bered)
6161 with self.assertRaises(DecodeError):
6162 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6163 with self.assertRaises(DecodeError):
6164 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6165 repr(seq_decoded_lenindef)
6166 list(seq_decoded_lenindef.pps())
6167 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6168 self.assertTrue(seq_decoded_lenindef.ready)
6170 for decoded, decoded_tail, encoded in (
6171 (seq_decoded, tail, seq_encoded),
6172 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6174 self.assertEqual(decoded_tail, tail_junk)
6175 self._assert_expects(decoded, expects)
6176 self.assertEqual(seq, decoded)
6177 self.assertEqual(decoded.encode(), seq_encoded)
6178 self.assertEqual(decoded.tlvlen, len(encoded))
6179 for expect in expects:
6180 if not expect["presented"]:
6181 self.assertNotIn(expect["name"], decoded)
6183 self.assertIn(expect["name"], decoded)
6184 obj = decoded[expect["name"]]
6185 self.assertTrue(obj.decoded)
6186 offset = obj.expl_offset if obj.expled else obj.offset
6187 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6188 self.assertSequenceEqual(
6189 seq_encoded[offset:offset + tlvlen],
6193 evgens = list(seq.decode_evgen(
6194 encoded + decoded_tail,
6195 decode_path=decode_path,
6196 ctx={"bered": True},
6198 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6199 for _decode_path, obj, _ in evgens[:-1]:
6200 self.assertEqual(_decode_path[:-1], decode_path)
6203 _decode_path, obj, tail = evgens[-1]
6204 self.assertEqual(_decode_path, decode_path)
6208 assert_exceeding_data(
6210 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6214 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6215 @given(data_strategy())
6216 def test_symmetric_with_seq(self, d):
6217 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6218 self.assertTrue(seq.ready)
6219 seq_encoded = seq.encode()
6220 self.assertEqual(encode2pass(seq), seq_encoded)
6221 seq_decoded, tail = seq.decode(seq_encoded)
6222 self.assertEqual(tail, b"")
6223 self.assertTrue(seq.ready)
6224 self.assertEqual(seq, seq_decoded)
6225 self.assertEqual(seq_decoded.encode(), seq_encoded)
6226 for expect_outer in expect_outers:
6227 if not expect_outer["presented"]:
6228 self.assertNotIn(expect_outer["name"], seq_decoded)
6230 self.assertIn(expect_outer["name"], seq_decoded)
6231 obj = seq_decoded[expect_outer["name"]]
6232 self.assertTrue(obj.decoded)
6233 offset = obj.expl_offset if obj.expled else obj.offset
6234 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6235 self.assertSequenceEqual(
6236 seq_encoded[offset:offset + tlvlen],
6239 self._assert_expects(obj, expect_outer["expects"])
6241 @given(data_strategy())
6242 def test_default_disappears(self, d):
6243 _schema = list(d.draw(dictionaries(
6245 sets(integers(), min_size=2, max_size=2),
6249 class Seq(self.base_klass):
6251 (n, Integer(default=d))
6252 for n, (_, d) in _schema
6255 for name, (value, _) in _schema:
6256 seq[name] = Integer(value)
6257 self.assertEqual(len(seq._value), len(_schema))
6258 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6259 self.assertGreater(len(seq.encode()), len(empty_seq))
6260 for name, (_, default) in _schema:
6261 seq[name] = Integer(default)
6262 self.assertEqual(len(seq._value), 0)
6263 self.assertSequenceEqual(seq.encode(), empty_seq)
6265 @given(data_strategy())
6266 def test_encoded_default_not_accepted(self, d):
6267 _schema = list(d.draw(dictionaries(
6272 tags = [tag_encode(tag) for tag in d.draw(sets(
6273 integers(min_value=1),
6274 min_size=len(_schema),
6275 max_size=len(_schema),
6278 class SeqWithoutDefault(self.base_klass):
6280 (n, Integer(impl=t))
6281 for (n, _), t in zip(_schema, tags)
6283 seq_without_default = SeqWithoutDefault()
6284 for name, value in _schema:
6285 seq_without_default[name] = Integer(value)
6286 seq_encoded = seq_without_default.encode()
6288 class SeqWithDefault(self.base_klass):
6290 (n, Integer(default=v, impl=t))
6291 for (n, v), t in zip(_schema, tags)
6293 seq_with_default = SeqWithDefault()
6294 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6295 seq_with_default.decode(seq_encoded)
6296 for ctx in ({"bered": True}, {"allow_default_values": True}):
6297 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6298 self.assertTrue(seq_decoded.ber_encoded)
6299 self.assertTrue(seq_decoded.bered)
6300 seq_decoded = copy(seq_decoded)
6301 self.assertTrue(seq_decoded.ber_encoded)
6302 self.assertTrue(seq_decoded.bered)
6303 for name, value in _schema:
6304 self.assertEqual(seq_decoded[name], seq_with_default[name])
6305 self.assertEqual(seq_decoded[name], value)
6307 @given(data_strategy())
6308 def test_missing_from_spec(self, d):
6309 names = list(d.draw(sets(text_letters(), min_size=2)))
6310 tags = [tag_encode(tag) for tag in d.draw(sets(
6311 integers(min_value=1),
6312 min_size=len(names),
6313 max_size=len(names),
6315 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6317 class SeqFull(self.base_klass):
6318 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6319 seq_full = SeqFull()
6320 for i, name in enumerate(names):
6321 seq_full[name] = Integer(i)
6322 seq_encoded = seq_full.encode()
6323 altered = names_tags[:-2] + names_tags[-1:]
6325 class SeqMissing(self.base_klass):
6326 schema = [(n, Integer(impl=t)) for n, t in altered]
6327 seq_missing = SeqMissing()
6328 with self.assertRaises(TagMismatch):
6329 seq_missing.decode(seq_encoded)
6331 def test_bered(self):
6332 class Seq(self.base_klass):
6333 schema = (("underlying", Boolean()),)
6334 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6335 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6336 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6337 self.assertFalse(decoded.ber_encoded)
6338 self.assertFalse(decoded.lenindef)
6339 self.assertTrue(decoded.bered)
6340 decoded = copy(decoded)
6341 self.assertFalse(decoded.ber_encoded)
6342 self.assertFalse(decoded.lenindef)
6343 self.assertTrue(decoded.bered)
6345 class Seq(self.base_klass):
6346 schema = (("underlying", OctetString()),)
6348 tag_encode(form=TagFormConstructed, num=4) +
6350 OctetString(b"whatever").encode() +
6353 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6354 with self.assertRaises(DecodeError):
6355 Seq().decode(encoded)
6356 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6357 self.assertFalse(decoded.ber_encoded)
6358 self.assertFalse(decoded.lenindef)
6359 self.assertTrue(decoded.bered)
6360 decoded = copy(decoded)
6361 self.assertFalse(decoded.ber_encoded)
6362 self.assertFalse(decoded.lenindef)
6363 self.assertTrue(decoded.bered)
6366 class TestSequence(SeqMixing, CommonMixin, TestCase):
6367 base_klass = Sequence
6373 def test_remaining(self, value, junk):
6374 class Seq(Sequence):
6376 ("whatever", Integer()),
6378 int_encoded = Integer(value).encode()
6380 Sequence.tag_default,
6381 len_encode(len(int_encoded + junk)),
6384 with assertRaisesRegex(self, DecodeError, "remaining"):
6385 Seq().decode(junked)
6387 @given(sets(text_letters(), min_size=2))
6388 def test_obj_unknown(self, names):
6389 missing = names.pop()
6391 class Seq(Sequence):
6392 schema = [(n, Boolean()) for n in names]
6394 with self.assertRaises(ObjUnknown) as err:
6397 with self.assertRaises(ObjUnknown) as err:
6398 seq[missing] = Boolean()
6401 def test_x690_vector(self):
6402 class Seq(Sequence):
6404 ("name", IA5String()),
6407 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6408 self.assertEqual(seq["name"], "Smith")
6409 self.assertEqual(seq["ok"], True)
6412 class TestSet(SeqMixing, CommonMixin, TestCase):
6415 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6416 @given(data_strategy())
6417 def test_sorted(self, d):
6418 class DummySeq(Sequence):
6419 schema = (("null", Null()),)
6421 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6422 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6423 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6424 tag_nums -= set([dummy_seq_tag_num])
6425 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6426 _schema.append(("seq", DummySeq()))
6429 schema = d.draw(permutations(_schema))
6431 for name, _ in _schema:
6433 seq[name] = OctetString(name.encode("ascii"))
6434 seq["seq"] = DummySeq((("null", Null()),))
6436 seq_encoded = seq.encode()
6437 seq_decoded, _ = seq.decode(seq_encoded)
6438 seq_encoded_expected = []
6439 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6440 if tag_num == dummy_seq_tag_num:
6441 seq_encoded_expected.append(seq["seq"].encode())
6443 seq_encoded_expected.append(seq[str(tag_num)].encode())
6444 self.assertSequenceEqual(
6445 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6446 b"".join(seq_encoded_expected),
6449 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6450 encoded += seq["seq"].encode()
6451 seq_encoded = b"".join((
6453 len_encode(len(encoded)),
6456 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6457 seq.decode(seq_encoded)
6458 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6459 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6460 self.assertTrue(seq_decoded.ber_encoded)
6461 self.assertTrue(seq_decoded.bered)
6462 seq_decoded = copy(seq_decoded)
6463 self.assertTrue(seq_decoded.ber_encoded)
6464 self.assertTrue(seq_decoded.bered)
6466 def test_same_value_twice(self):
6469 ("bool", Boolean()),
6473 encoded = b"".join((
6474 Integer(123).encode(),
6475 Integer(234).encode(),
6476 Boolean(True).encode(),
6478 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6479 with self.assertRaises(TagMismatch):
6480 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6484 def seqof_values_strategy(draw, schema=None, do_expl=False):
6486 schema = draw(sampled_from((Boolean(), Integer())))
6487 bound_min, bound_max = sorted(draw(sets(
6488 integers(min_value=0, max_value=10),
6492 if isinstance(schema, Boolean):
6493 values_generator = booleans().map(Boolean)
6494 elif isinstance(schema, Integer):
6495 values_generator = integers().map(Integer)
6496 values_generator = lists(
6501 values = draw(one_of(none(), values_generator))
6505 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6507 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6508 default = draw(one_of(none(), values_generator))
6509 optional = draw(one_of(none(), booleans()))
6511 draw(integers(min_value=0)),
6512 draw(integers(min_value=0)),
6513 draw(integers(min_value=0)),
6518 (bound_min, bound_max),
6527 class SeqOfMixing(object):
6528 def test_invalid_value_type(self):
6529 with self.assertRaises(InvalidValueType) as err:
6530 self.base_klass(123)
6533 def test_invalid_values_type(self):
6534 class SeqOf(self.base_klass):
6536 with self.assertRaises(InvalidValueType) as err:
6537 SeqOf([Integer(123), Boolean(False), Integer(234)])
6540 def test_schema_required(self):
6541 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6542 self.base_klass.__mro__[1]()
6544 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6545 def test_comparison(self, value1, value2, tag1, tag2):
6546 class SeqOf(self.base_klass):
6548 obj1 = SeqOf([Boolean(value1)])
6549 obj2 = SeqOf([Boolean(value2)])
6550 self.assertEqual(obj1 == obj2, value1 == value2)
6551 self.assertEqual(obj1 != obj2, value1 != value2)
6552 self.assertEqual(obj1 == list(obj2), value1 == value2)
6553 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6554 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6555 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6556 self.assertEqual(obj1 == obj2, tag1 == tag2)
6557 self.assertEqual(obj1 != obj2, tag1 != tag2)
6559 @given(lists(booleans()))
6560 def test_iter(self, values):
6561 class SeqOf(self.base_klass):
6563 obj = SeqOf([Boolean(value) for value in values])
6564 self.assertEqual(len(obj), len(values))
6565 for i, value in enumerate(obj):
6566 self.assertEqual(value, values[i])
6568 @given(data_strategy())
6569 def test_ready(self, d):
6570 ready = [Integer(v) for v in d.draw(lists(
6577 range(d.draw(integers(min_value=1, max_value=5)))
6580 class SeqOf(self.base_klass):
6582 values = d.draw(permutations(ready + non_ready))
6584 for value in values:
6586 self.assertFalse(seqof.ready)
6589 pprint(seqof, big_blobs=True, with_decode_path=True)
6590 with self.assertRaises(ObjNotReady) as err:
6593 with self.assertRaises(ObjNotReady) as err:
6595 for i, value in enumerate(values):
6596 self.assertEqual(seqof[i], value)
6597 if not seqof[i].ready:
6598 seqof[i] = Integer(i)
6599 self.assertTrue(seqof.ready)
6602 pprint(seqof, big_blobs=True, with_decode_path=True)
6604 def test_spec_mismatch(self):
6605 class SeqOf(self.base_klass):
6608 seqof.append(Integer(123))
6609 with self.assertRaises(ValueError):
6610 seqof.append(Boolean(False))
6611 with self.assertRaises(ValueError):
6612 seqof[0] = Boolean(False)
6614 @given(data_strategy())
6615 def test_bounds_satisfied(self, d):
6616 class SeqOf(self.base_klass):
6618 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6619 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6620 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6621 SeqOf(value=value, bounds=(bound_min, bound_max))
6623 @given(data_strategy())
6624 def test_bounds_unsatisfied(self, d):
6625 class SeqOf(self.base_klass):
6627 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6628 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6629 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6630 with self.assertRaises(BoundsError) as err:
6631 SeqOf(value=value, bounds=(bound_min, bound_max))
6633 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6634 SeqOf(bounds=(bound_min, bound_max)).decode(
6635 SeqOf(value).encode()
6638 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6639 SeqOf(bounds=(bound_min, bound_max)).decode(
6640 encode2pass(SeqOf(value))
6642 value = [Boolean(True)] * d.draw(integers(
6643 min_value=bound_max + 1,
6644 max_value=bound_max + 10,
6646 with self.assertRaises(BoundsError) as err:
6647 SeqOf(value=value, bounds=(bound_min, bound_max))
6649 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6650 SeqOf(bounds=(bound_min, bound_max)).decode(
6651 SeqOf(value).encode()
6654 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6655 SeqOf(bounds=(bound_min, bound_max)).decode(
6656 encode2pass(SeqOf(value))
6659 @given(integers(min_value=1, max_value=10))
6660 def test_out_of_bounds(self, bound_max):
6661 class SeqOf(self.base_klass):
6663 bounds = (0, bound_max)
6665 for _ in range(bound_max):
6666 seqof.append(Integer(123))
6667 with self.assertRaises(BoundsError):
6668 seqof.append(Integer(123))
6670 @given(data_strategy())
6671 def test_call(self, d):
6681 ) = d.draw(seqof_values_strategy())
6683 class SeqOf(self.base_klass):
6684 schema = schema_initial
6685 obj_initial = SeqOf(
6686 value=value_initial,
6687 bounds=bounds_initial,
6690 default=default_initial,
6691 optional=optional_initial or False,
6692 _decoded=_decoded_initial,
6703 ) = d.draw(seqof_values_strategy(
6704 schema=schema_initial,
6705 do_expl=impl_initial is None,
6707 if (default is None) and (obj_initial.default is not None):
6710 (bounds is None) and
6711 (value is not None) and
6712 (bounds_initial is not None) and
6713 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6717 (bounds is None) and
6718 (default is not None) and
6719 (bounds_initial is not None) and
6720 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6732 value_expected = default if value is None else value
6734 default_initial if value_expected is None
6737 value_expected = () if value_expected is None else value_expected
6738 self.assertEqual(obj, value_expected)
6739 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6740 self.assertEqual(obj.expl_tag, expl or expl_initial)
6743 default_initial if default is None else default,
6745 if obj.default is None:
6746 optional = optional_initial if optional is None else optional
6747 optional = False if optional is None else optional
6750 self.assertEqual(obj.optional, optional)
6752 (obj._bound_min, obj._bound_max),
6753 bounds or bounds_initial or (0, float("+inf")),
6756 @given(seqof_values_strategy())
6757 def test_copy(self, values):
6758 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6760 class SeqOf(self.base_klass):
6762 register_class(SeqOf)
6769 optional=optional or False,
6772 for copy_func in copy_funcs:
6773 obj_copied = copy_func(obj)
6774 self.assert_copied_basic_fields(obj, obj_copied)
6775 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6776 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6777 self.assertEqual(obj._value, obj_copied._value)
6781 integers(min_value=1).map(tag_encode),
6783 def test_stripped(self, values, tag_impl):
6784 class SeqOf(self.base_klass):
6785 schema = OctetString()
6786 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6787 with self.assertRaises(NotEnoughData):
6788 obj.decode(obj.encode()[:-1])
6792 integers(min_value=1).map(tag_ctxc),
6794 def test_stripped_expl(self, values, tag_expl):
6795 class SeqOf(self.base_klass):
6796 schema = OctetString()
6797 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6798 with self.assertRaises(NotEnoughData):
6799 obj.decode(obj.encode()[:-1])
6802 integers(min_value=31),
6803 integers(min_value=0),
6806 def test_bad_tag(self, tag, offset, decode_path):
6807 with self.assertRaises(DecodeError) as err:
6808 self.base_klass().decode(
6809 tag_encode(tag)[:-1],
6811 decode_path=decode_path,
6814 self.assertEqual(err.exception.offset, offset)
6815 self.assertEqual(err.exception.decode_path, decode_path)
6818 integers(min_value=128),
6819 integers(min_value=0),
6822 def test_bad_len(self, l, offset, decode_path):
6823 with self.assertRaises(DecodeError) as err:
6824 self.base_klass().decode(
6825 self.base_klass.tag_default + len_encode(l)[:-1],
6827 decode_path=decode_path,
6830 self.assertEqual(err.exception.offset, offset)
6831 self.assertEqual(err.exception.decode_path, decode_path)
6833 @given(binary(min_size=1))
6834 def test_tag_mismatch(self, impl):
6835 assume(impl != self.base_klass.tag_default)
6836 with self.assertRaises(TagMismatch):
6837 self.base_klass(impl=impl).decode(self.base_klass().encode())
6839 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6841 seqof_values_strategy(schema=Integer()),
6842 lists(integers().map(Integer)),
6843 integers(min_value=1).map(tag_ctxc),
6844 integers(min_value=0),
6848 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6849 _, _, _, _, _, default, optional, _decoded = values
6851 class SeqOf(self.base_klass):
6861 pprint(obj, big_blobs=True, with_decode_path=True)
6862 self.assertFalse(obj.expled)
6863 obj_encoded = obj.encode()
6864 self.assertEqual(encode2pass(obj), obj_encoded)
6865 obj_encoded_cer = encode_cer(obj)
6866 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6867 self.assertSequenceEqual(
6868 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6871 obj_expled = obj(value, expl=tag_expl)
6872 self.assertTrue(obj_expled.expled)
6874 list(obj_expled.pps())
6875 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6876 obj_expled_encoded = obj_expled.encode()
6877 ctx_copied = deepcopy(ctx_dummy)
6878 obj_decoded, tail = obj_expled.decode(
6879 obj_expled_encoded + tail_junk,
6883 self.assertDictEqual(ctx_copied, ctx_dummy)
6885 list(obj_decoded.pps())
6886 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6887 self.assertEqual(tail, tail_junk)
6888 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6889 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6890 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6891 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6893 obj_decoded.expl_llen,
6894 len(len_encode(len(obj_encoded))),
6896 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6897 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6900 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6902 self.assertEqual(obj_decoded.expl_offset, offset)
6903 for obj_inner in obj_decoded:
6904 self.assertIn(obj_inner, obj_decoded)
6905 self.assertSequenceEqual(
6908 obj_inner.offset - offset:
6909 obj_inner.offset + obj_inner.tlvlen - offset
6913 t, _, lv = tag_strip(obj_encoded)
6914 _, _, v = len_decode(lv)
6915 obj_encoded_lenindef = t + LENINDEF + v + EOC
6916 with self.assertRaises(DecodeError):
6917 obj.decode(obj_encoded_lenindef)
6918 obj_decoded_lenindef, tail_lenindef = obj.decode(
6919 obj_encoded_lenindef + tail_junk,
6920 ctx={"bered": True},
6922 self.assertTrue(obj_decoded_lenindef.lenindef)
6923 self.assertTrue(obj_decoded_lenindef.bered)
6924 obj_decoded_lenindef = copy(obj_decoded_lenindef)
6925 self.assertTrue(obj_decoded_lenindef.lenindef)
6926 self.assertTrue(obj_decoded_lenindef.bered)
6927 repr(obj_decoded_lenindef)
6928 list(obj_decoded_lenindef.pps())
6929 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
6930 self.assertEqual(tail_lenindef, tail_junk)
6931 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
6932 with self.assertRaises(DecodeError):
6933 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
6934 with self.assertRaises(DecodeError):
6935 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
6937 evgens = list(obj.decode_evgen(
6938 obj_encoded_lenindef + tail_junk,
6939 decode_path=decode_path,
6940 ctx={"bered": True},
6942 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
6943 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
6944 self.assertEqual(_decode_path, decode_path + (str(i),))
6947 _decode_path, obj, tail = evgens[-1]
6948 self.assertEqual(_decode_path, decode_path)
6952 assert_exceeding_data(
6954 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
6958 def test_bered(self):
6959 class SeqOf(self.base_klass):
6961 encoded = Boolean(False).encode()
6962 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
6963 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
6964 with self.assertRaises(DecodeError):
6965 SeqOf().decode(encoded)
6966 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
6967 self.assertFalse(decoded.ber_encoded)
6968 self.assertFalse(decoded.lenindef)
6969 self.assertTrue(decoded.bered)
6970 decoded = copy(decoded)
6971 self.assertFalse(decoded.ber_encoded)
6972 self.assertFalse(decoded.lenindef)
6973 self.assertTrue(decoded.bered)
6975 class SeqOf(self.base_klass):
6976 schema = OctetString()
6977 encoded = OctetString(b"whatever").encode()
6979 tag_encode(form=TagFormConstructed, num=4) +
6981 OctetString(b"whatever").encode() +
6984 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
6985 with self.assertRaises(DecodeError):
6986 SeqOf().decode(encoded)
6987 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
6988 self.assertFalse(decoded.ber_encoded)
6989 self.assertFalse(decoded.lenindef)
6990 self.assertTrue(decoded.bered)
6991 decoded = copy(decoded)
6992 self.assertFalse(decoded.ber_encoded)
6993 self.assertFalse(decoded.lenindef)
6994 self.assertTrue(decoded.bered)
6997 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
6998 class SeqOf(SequenceOf):
7002 def _test_symmetric_compare_objs(self, obj1, obj2):
7003 self.assertEqual(obj1, obj2)
7004 self.assertSequenceEqual(list(obj1), list(obj2))
7006 def test_iterator_pickling(self):
7007 class SeqOf(SequenceOf):
7009 register_class(SeqOf)
7012 seqof = seqof(iter(six_xrange(10)))
7013 with assertRaisesRegex(self, ValueError, "iterator"):
7016 def test_iterator_bounds(self):
7017 class SeqOf(SequenceOf):
7022 for i in six_xrange(n):
7025 seqof = SeqOf(gen(n))
7026 self.assertTrue(seqof.ready)
7027 with self.assertRaises(BoundsError):
7029 self.assertFalse(seqof.ready)
7030 seqof = seqof(gen(n))
7031 self.assertTrue(seqof.ready)
7032 with self.assertRaises(BoundsError):
7034 self.assertFalse(seqof.ready)
7036 def test_iterator_twice(self):
7037 class SeqOf(SequenceOf):
7039 bounds = (1, float("+inf"))
7041 for i in six_xrange(10):
7043 seqof = SeqOf(gen())
7044 self.assertTrue(seqof.ready)
7046 self.assertFalse(seqof.ready)
7047 register_class(SeqOf)
7050 def test_iterator_2pass(self):
7051 class SeqOf(SequenceOf):
7053 bounds = (1, float("+inf"))
7055 for i in six_xrange(10):
7057 seqof = SeqOf(gen())
7058 self.assertTrue(seqof.ready)
7059 _, state = seqof.encode1st()
7060 self.assertFalse(seqof.ready)
7061 seqof = seqof(gen())
7062 self.assertTrue(seqof.ready)
7064 seqof.encode2nd(buf.write, iter(state))
7065 self.assertSequenceEqual(
7066 [int(i) for i in seqof.decod(buf.getvalue())],
7070 def test_non_ready_bound_min(self):
7071 class SeqOf(SequenceOf):
7073 bounds = (1, float("+inf"))
7075 self.assertFalse(seqof.ready)
7078 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7083 def _test_symmetric_compare_objs(self, obj1, obj2):
7084 self.assertSetEqual(
7085 set(int(v) for v in obj1),
7086 set(int(v) for v in obj2),
7089 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7090 @given(data_strategy())
7091 def test_sorted(self, d):
7092 values = [OctetString(v) for v in d.draw(lists(binary()))]
7095 schema = OctetString()
7097 seq_encoded = seq.encode()
7098 seq_decoded, _ = seq.decode(seq_encoded)
7099 self.assertSequenceEqual(
7100 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7101 b"".join(sorted([v.encode() for v in values])),
7104 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7105 @given(data_strategy())
7106 def test_unsorted(self, d):
7107 values = [OctetString(v).encode() for v in d.draw(sets(
7108 binary(min_size=1, max_size=5),
7112 values = d.draw(permutations(values))
7113 assume(values != sorted(values))
7114 encoded = b"".join(values)
7115 seq_encoded = b"".join((
7117 len_encode(len(encoded)),
7122 schema = OctetString()
7124 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7125 seq.decode(seq_encoded)
7127 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7128 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7129 self.assertTrue(seq_decoded.ber_encoded)
7130 self.assertTrue(seq_decoded.bered)
7131 seq_decoded = copy(seq_decoded)
7132 self.assertTrue(seq_decoded.ber_encoded)
7133 self.assertTrue(seq_decoded.bered)
7134 self.assertSequenceEqual(
7135 [obj.encode() for obj in seq_decoded],
7140 class TestGoMarshalVectors(TestCase):
7142 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7143 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7144 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7145 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7146 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7148 class Seq(Sequence):
7150 ("erste", Integer()),
7151 ("zweite", Integer(optional=True))
7154 seq["erste"] = Integer(64)
7155 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7156 seq["erste"] = Integer(0x123456)
7157 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7158 seq["erste"] = Integer(64)
7159 seq["zweite"] = Integer(65)
7160 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7162 class NestedSeq(Sequence):
7166 seq["erste"] = Integer(127)
7167 seq["zweite"] = None
7168 nested = NestedSeq()
7169 nested["nest"] = seq
7170 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7172 self.assertSequenceEqual(
7173 OctetString(b"\x01\x02\x03").encode(),
7174 hexdec("0403010203"),
7177 class Seq(Sequence):
7179 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7182 seq["erste"] = Integer(64)
7183 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7185 class Seq(Sequence):
7187 ("erste", Integer(expl=tag_ctxc(5))),
7190 seq["erste"] = Integer(64)
7191 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7193 class Seq(Sequence):
7196 impl=tag_encode(0, klass=TagClassContext),
7201 seq["erste"] = Null()
7202 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7204 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7206 self.assertSequenceEqual(
7207 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7208 hexdec("170d3730303130313030303030305a"),
7210 self.assertSequenceEqual(
7211 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7212 hexdec("170d3039313131353232353631365a"),
7214 self.assertSequenceEqual(
7215 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7216 hexdec("180f32313030303430353132303130315a"),
7219 class Seq(Sequence):
7221 ("erste", GeneralizedTime()),
7224 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7225 self.assertSequenceEqual(
7227 hexdec("3011180f32303039313131353232353631365a"),
7230 self.assertSequenceEqual(
7231 BitString((1, b"\x80")).encode(),
7234 self.assertSequenceEqual(
7235 BitString((12, b"\x81\xF0")).encode(),
7236 hexdec("03030481f0"),
7239 self.assertSequenceEqual(
7240 ObjectIdentifier("1.2.3.4").encode(),
7241 hexdec("06032a0304"),
7243 self.assertSequenceEqual(
7244 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7245 hexdec("06092a864888932d010105"),
7247 self.assertSequenceEqual(
7248 ObjectIdentifier("2.100.3").encode(),
7249 hexdec("0603813403"),
7252 self.assertSequenceEqual(
7253 PrintableString("test").encode(),
7254 hexdec("130474657374"),
7256 self.assertSequenceEqual(
7257 PrintableString("x" * 127).encode(),
7258 hexdec("137F" + "78" * 127),
7260 self.assertSequenceEqual(
7261 PrintableString("x" * 128).encode(),
7262 hexdec("138180" + "78" * 128),
7264 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7266 class Seq(Sequence):
7268 ("erste", IA5String()),
7271 seq["erste"] = IA5String("test")
7272 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7274 class Seq(Sequence):
7276 ("erste", PrintableString()),
7279 seq["erste"] = PrintableString("test")
7280 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7281 # Asterisk is actually not allowable
7282 PrintableString._allowable_chars |= set(b"*")
7283 seq["erste"] = PrintableString("test*")
7284 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7285 PrintableString._allowable_chars -= set(b"*")
7287 class Seq(Sequence):
7289 ("erste", Any(optional=True)),
7290 ("zweite", Integer()),
7293 seq["zweite"] = Integer(64)
7294 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7299 seq.append(Integer(10))
7300 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7302 class _SeqOf(SequenceOf):
7303 schema = PrintableString()
7305 class SeqOf(SequenceOf):
7308 _seqof.append(PrintableString("1"))
7310 seqof.append(_seqof)
7311 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7313 class Seq(Sequence):
7315 ("erste", Integer(default=1)),
7318 seq["erste"] = Integer(0)
7319 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7320 seq["erste"] = Integer(1)
7321 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7322 seq["erste"] = Integer(2)
7323 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7326 class TestPP(TestCase):
7327 @given(data_strategy())
7328 def test_oid_printing(self, d):
7330 str(ObjectIdentifier(k)): v * 2
7331 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7333 chosen = d.draw(sampled_from(sorted(oids)))
7334 chosen_id = oids[chosen]
7335 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7336 self.assertNotIn(chosen_id, pp_console_row(pp))
7339 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7343 class TestAutoAddSlots(TestCase):
7345 class Inher(Integer):
7348 with self.assertRaises(AttributeError):
7350 inher.unexistent = "whatever"
7353 class TestOIDDefines(TestCase):
7354 @given(data_strategy())
7355 def runTest(self, d):
7356 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7357 value_name_chosen = d.draw(sampled_from(value_names))
7359 ObjectIdentifier(oid)
7360 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7362 oid_chosen = d.draw(sampled_from(oids))
7363 values = d.draw(lists(
7365 min_size=len(value_names),
7366 max_size=len(value_names),
7368 for definable_class in (Any, OctetString, BitString):
7370 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7371 oid: Integer() for oid in oids[:-1]
7374 for i, value_name in enumerate(value_names):
7375 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7377 class Seq(Sequence):
7380 for value_name, value in zip(value_names, values):
7381 seq[value_name] = definable_class(Integer(value).encode())
7382 seq["type"] = oid_chosen
7383 seq, _ = Seq().decode(seq.encode())
7384 for value_name in value_names:
7385 if value_name == value_name_chosen:
7387 self.assertIsNone(seq[value_name].defined)
7388 if value_name_chosen in oids[:-1]:
7389 self.assertIsNotNone(seq[value_name_chosen].defined)
7390 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7391 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7394 pprint(seq, big_blobs=True, with_decode_path=True)
7397 class TestDefinesByPath(TestCase):
7398 def test_generated(self):
7399 class Seq(Sequence):
7401 ("type", ObjectIdentifier()),
7402 ("value", OctetString(expl=tag_ctxc(123))),
7405 class SeqInner(Sequence):
7407 ("typeInner", ObjectIdentifier()),
7408 ("valueInner", Any()),
7411 class PairValue(SetOf):
7414 class Pair(Sequence):
7416 ("type", ObjectIdentifier()),
7417 ("value", PairValue()),
7420 class Pairs(SequenceOf):
7427 type_octet_stringed,
7429 ObjectIdentifier(oid)
7430 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7432 seq_integered = Seq()
7433 seq_integered["type"] = type_integered
7434 seq_integered["value"] = OctetString(Integer(123).encode())
7435 seq_integered_raw = seq_integered.encode()
7439 (type_octet_stringed, OctetString(b"whatever")),
7440 (type_integered, Integer(123)),
7441 (type_octet_stringed, OctetString(b"whenever")),
7442 (type_integered, Integer(234)),
7444 for t, v in pairs_input:
7447 ("value", PairValue((Any(v),))),
7449 seq_inner = SeqInner()
7450 seq_inner["typeInner"] = type_innered
7451 seq_inner["valueInner"] = Any(pairs)
7452 seq_sequenced = Seq()
7453 seq_sequenced["type"] = type_sequenced
7454 seq_sequenced["value"] = OctetString(seq_inner.encode())
7455 seq_sequenced_raw = seq_sequenced.encode()
7457 list(seq_sequenced.pps())
7458 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7460 defines_by_path = []
7461 ctx_copied = deepcopy(ctx_dummy)
7462 seq_integered, _ = Seq().decode(
7466 self.assertDictEqual(ctx_copied, ctx_dummy)
7467 self.assertIsNone(seq_integered["value"].defined)
7468 defines_by_path.append(
7469 (("type",), ((("value",), {
7470 type_integered: Integer(),
7471 type_sequenced: SeqInner(),
7474 ctx_copied["defines_by_path"] = defines_by_path
7475 seq_integered, _ = Seq().decode(
7479 del ctx_copied["defines_by_path"]
7480 self.assertDictEqual(ctx_copied, ctx_dummy)
7481 self.assertIsNotNone(seq_integered["value"].defined)
7482 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7483 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7484 self.assertTrue(seq_integered_raw[
7485 seq_integered["value"].defined[1].offset:
7486 ].startswith(Integer(123).encode()))
7488 list(seq_integered.pps())
7489 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7491 ctx_copied["defines_by_path"] = defines_by_path
7492 seq_sequenced, _ = Seq().decode(
7496 del ctx_copied["defines_by_path"]
7497 self.assertDictEqual(ctx_copied, ctx_dummy)
7498 self.assertIsNotNone(seq_sequenced["value"].defined)
7499 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7500 seq_inner = seq_sequenced["value"].defined[1]
7501 self.assertIsNone(seq_inner["valueInner"].defined)
7503 list(seq_sequenced.pps())
7504 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7506 defines_by_path.append((
7507 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7508 ((("valueInner",), {type_innered: Pairs()}),),
7510 ctx_copied["defines_by_path"] = defines_by_path
7511 seq_sequenced, _ = Seq().decode(
7515 del ctx_copied["defines_by_path"]
7516 self.assertDictEqual(ctx_copied, ctx_dummy)
7517 self.assertIsNotNone(seq_sequenced["value"].defined)
7518 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7519 seq_inner = seq_sequenced["value"].defined[1]
7520 self.assertIsNotNone(seq_inner["valueInner"].defined)
7521 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7522 pairs = seq_inner["valueInner"].defined[1]
7524 self.assertIsNone(pair["value"][0].defined)
7526 list(seq_sequenced.pps())
7527 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7529 defines_by_path.append((
7532 DecodePathDefBy(type_sequenced),
7534 DecodePathDefBy(type_innered),
7539 type_integered: Integer(),
7540 type_octet_stringed: OctetString(),
7543 ctx_copied["defines_by_path"] = defines_by_path
7544 seq_sequenced, _ = Seq().decode(
7548 del ctx_copied["defines_by_path"]
7549 self.assertDictEqual(ctx_copied, ctx_dummy)
7550 self.assertIsNotNone(seq_sequenced["value"].defined)
7551 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7552 seq_inner = seq_sequenced["value"].defined[1]
7553 self.assertIsNotNone(seq_inner["valueInner"].defined)
7554 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7555 pairs_got = seq_inner["valueInner"].defined[1]
7556 for pair_input, pair_got in zip(pairs_input, pairs_got):
7557 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7558 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7560 list(seq_sequenced.pps())
7561 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7563 @given(oid_strategy(), integers())
7564 def test_simple(self, oid, tgt):
7565 class Inner(Sequence):
7567 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7568 ObjectIdentifier(oid): Integer(),
7572 class Outer(Sequence):
7575 ("tgt", OctetString()),
7579 inner["oid"] = ObjectIdentifier(oid)
7581 outer["inner"] = inner
7582 outer["tgt"] = OctetString(Integer(tgt).encode())
7583 decoded, _ = Outer().decode(outer.encode())
7584 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7586 def test_remaining_data(self):
7587 oid = ObjectIdentifier("1.2.3")
7588 class Seq(Sequence):
7590 ("oid", ObjectIdentifier(defines=((("tgt",), {
7593 ("tgt", OctetString()),
7598 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7600 with assertRaisesRegex(self, DecodeError, "remaining data"):
7601 Seq().decode(seq.encode())
7603 def test_remaining_data_seqof(self):
7604 oid = ObjectIdentifier("1.2.3")
7606 schema = OctetString()
7608 class Seq(Sequence):
7610 ("oid", ObjectIdentifier(defines=((("tgt",), {
7618 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7620 with assertRaisesRegex(self, DecodeError, "remaining data"):
7621 Seq().decode(seq.encode())
7624 class TestAbsDecodePath(TestCase):
7626 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7627 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7629 def test_concat(self, decode_path, rel_path):
7630 dp = abs_decode_path(decode_path, rel_path)
7631 self.assertSequenceEqual(dp, decode_path + rel_path)
7635 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7636 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7638 def test_abs(self, decode_path, rel_path):
7639 self.assertSequenceEqual(
7640 abs_decode_path(decode_path, ("/",) + rel_path),
7645 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7646 integers(min_value=1, max_value=3),
7647 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7649 def test_dots(self, decode_path, number_of_dots, rel_path):
7650 self.assertSequenceEqual(
7651 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7652 decode_path[:-number_of_dots] + rel_path,
7656 class TestStrictDefaultExistence(TestCase):
7657 @given(data_strategy())
7658 def runTest(self, d):
7659 count = d.draw(integers(min_value=1, max_value=10))
7660 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7662 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7663 for i in range(count)
7665 for klass in (Sequence, Set):
7669 for i in range(count):
7670 seq["int%d" % i] = Integer(123)
7672 chosen_choice = "int%d" % chosen
7673 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7674 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7676 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7677 self.assertTrue(decoded.ber_encoded)
7678 self.assertTrue(decoded.bered)
7679 decoded = copy(decoded)
7680 self.assertTrue(decoded.ber_encoded)
7681 self.assertTrue(decoded.bered)
7682 decoded, _ = seq.decode(raw, ctx={"bered": True})
7683 self.assertTrue(decoded.ber_encoded)
7684 self.assertTrue(decoded.bered)
7685 decoded = copy(decoded)
7686 self.assertTrue(decoded.ber_encoded)
7687 self.assertTrue(decoded.bered)
7690 class TestX690PrefixedType(TestCase):
7692 self.assertSequenceEqual(
7693 VisibleString("Jones").encode(),
7694 hexdec("1A054A6F6E6573"),
7698 self.assertSequenceEqual(
7701 impl=tag_encode(3, klass=TagClassApplication),
7703 hexdec("43054A6F6E6573"),
7707 self.assertSequenceEqual(
7711 impl=tag_encode(3, klass=TagClassApplication),
7715 hexdec("A20743054A6F6E6573"),
7719 self.assertSequenceEqual(
7723 impl=tag_encode(3, klass=TagClassApplication),
7725 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7727 hexdec("670743054A6F6E6573"),
7731 self.assertSequenceEqual(
7732 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7733 hexdec("82054A6F6E6573"),
7737 class TestExplOOB(TestCase):
7739 expl = tag_ctxc(123)
7740 raw = Integer(123).encode() + Integer(234).encode()
7741 raw = b"".join((expl, len_encode(len(raw)), raw))
7742 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7743 Integer(expl=expl).decode(raw)
7744 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7747 class TestPickleDifferentVersion(TestCase):
7749 pickled = pickle_dumps(Integer(123), pickle_proto)
7751 version_orig = pyderasn.__version__
7752 pyderasn.__version__ += "different"
7753 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7754 pickle_loads(pickled)
7755 pyderasn.__version__ = version_orig
7756 pickle_loads(pickled)
7759 class TestCERSetOrdering(TestCase):
7760 def test_vectors(self):
7761 """Taken from X.690-201508
7765 ("c", Integer(impl=tag_ctxp(2))),
7766 ("d", Integer(impl=tag_ctxp(4))),
7771 ("g", Integer(impl=tag_ctxp(5))),
7772 ("h", Integer(impl=tag_ctxp(6))),
7777 ("j", Integer(impl=tag_ctxp(0))),
7788 ("a", Integer(impl=tag_ctxp(3))),
7789 ("b", B(expl=tag_ctxc(1))),
7794 ("a", Integer(123)),
7795 ("b", B(("d", Integer(234)))),
7796 ("e", E(("f", F(("g", Integer(345)))))),
7798 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7799 self.assertSequenceEqual(
7800 [i.__class__.__name__ for i in order],
7801 ("E", "B", "Integer"),