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):
279 @given(tag_classes, tag_forms, integers(min_value=31))
280 def test_leading_zero_byte(self, klass, form, num):
281 raw = tag_encode(klass=klass, form=form, num=num)
282 raw = b"".join((raw[:1], b"\x80", raw[1:]))
283 with assertRaisesRegex(self, DecodeError, "leading zero byte"):
287 class TestLenCoder(TestCase):
288 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
290 integers(min_value=0, max_value=127),
293 def test_short(self, l, junk):
294 raw = len_encode(l) + junk
295 decoded, llen, tail = len_decode(memoryview(raw))
296 self.assertEqual(decoded, l)
297 self.assertEqual(llen, 1)
298 self.assertEqual(len(raw), 1 + len(junk))
299 self.assertEqual(tail.tobytes(), junk)
301 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
303 integers(min_value=128),
306 def test_long(self, l, junk):
307 raw = len_encode(l) + junk
308 decoded, llen, tail = len_decode(memoryview(raw))
309 self.assertEqual(decoded, l)
310 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
311 self.assertEqual(llen, len(raw) - len(junk))
312 self.assertNotEqual(indexbytes(raw, 1), 0)
313 self.assertSequenceEqual(tail.tobytes(), junk)
315 def test_empty(self):
316 with self.assertRaises(NotEnoughData):
319 @given(integers(min_value=128))
320 def test_stripped(self, _len):
321 with self.assertRaises(NotEnoughData):
322 len_decode(len_encode(_len)[:-1])
325 text_printable = text(alphabet=printable, min_size=1)
329 def text_letters(draw):
330 result = draw(text(alphabet=ascii_letters, min_size=1))
332 result = result.encode("ascii")
336 class CommonMixin(object):
337 def test_tag_default(self):
338 obj = self.base_klass()
339 self.assertEqual(obj.tag, obj.tag_default)
341 def test_simultaneous_impl_expl(self):
342 with self.assertRaises(ValueError):
343 self.base_klass(impl=b"whatever", expl=b"whenever")
345 @given(binary(min_size=1), integers(), integers(), integers())
346 def test_decoded(self, impl, offset, llen, vlen):
347 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
348 self.assertEqual(obj.offset, offset)
349 self.assertEqual(obj.llen, llen)
350 self.assertEqual(obj.vlen, vlen)
351 self.assertEqual(obj.tlen, len(impl))
352 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
354 @given(binary(min_size=1))
355 def test_impl_inherited(self, impl_tag):
356 class Inherited(self.base_klass):
359 self.assertSequenceEqual(obj.impl, impl_tag)
360 self.assertFalse(obj.expled)
362 tag_class, _, tag_num = tag_decode(impl_tag)
363 self.assertEqual(obj.tag_order, (tag_class, tag_num))
365 @given(binary(min_size=1))
366 def test_expl_inherited(self, expl_tag):
367 class Inherited(self.base_klass):
370 self.assertSequenceEqual(obj.expl, expl_tag)
371 self.assertTrue(obj.expled)
373 tag_class, _, tag_num = tag_decode(expl_tag)
374 self.assertEqual(obj.tag_order, (tag_class, tag_num))
376 def assert_copied_basic_fields(self, obj, obj_copied):
377 self.assertEqual(obj, obj_copied)
378 self.assertSequenceEqual(obj.tag, obj_copied.tag)
379 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
380 self.assertEqual(obj.default, obj_copied.default)
381 self.assertEqual(obj.optional, obj_copied.optional)
382 self.assertEqual(obj.offset, obj_copied.offset)
383 self.assertEqual(obj.llen, obj_copied.llen)
384 self.assertEqual(obj.vlen, obj_copied.vlen)
386 self.assertEqual(obj.tag_order, obj_copied.tag_order)
390 def boolean_values_strategy(draw, do_expl=False):
391 value = draw(one_of(none(), booleans()))
395 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
397 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
398 default = draw(one_of(none(), booleans()))
399 optional = draw(one_of(none(), booleans()))
401 draw(integers(min_value=0)),
402 draw(integers(min_value=0)),
403 draw(integers(min_value=0)),
405 return (value, impl, expl, default, optional, _decoded)
408 class BooleanInherited(Boolean):
412 class TestBoolean(CommonMixin, TestCase):
415 def test_invalid_value_type(self):
416 with self.assertRaises(InvalidValueType) as err:
421 def test_optional(self, optional):
422 obj = Boolean(default=Boolean(False), optional=optional)
423 self.assertTrue(obj.optional)
426 def test_ready(self, value):
428 self.assertFalse(obj.ready)
431 pprint(obj, big_blobs=True, with_decode_path=True)
432 with self.assertRaises(ObjNotReady) as err:
434 with self.assertRaises(ObjNotReady) as err:
438 self.assertTrue(obj.ready)
441 pprint(obj, big_blobs=True, with_decode_path=True)
443 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
444 def test_comparison(self, value1, value2, tag1, tag2):
445 for klass in (Boolean, BooleanInherited):
448 self.assertEqual(obj1 == obj2, value1 == value2)
449 self.assertEqual(obj1 != obj2, value1 != value2)
450 self.assertEqual(obj1 == bool(obj2), value1 == value2)
451 obj1 = klass(value1, impl=tag1)
452 obj2 = klass(value1, impl=tag2)
453 self.assertEqual(obj1 == obj2, tag1 == tag2)
454 self.assertEqual(obj1 != obj2, tag1 != tag2)
456 @given(data_strategy())
457 def test_call(self, d):
458 for klass in (Boolean, BooleanInherited):
466 ) = d.draw(boolean_values_strategy())
472 optional_initial or False,
482 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
483 obj = obj_initial(value, impl, expl, default, optional)
485 value_expected = default if value is None else value
487 default_initial if value_expected is None
490 self.assertEqual(obj, value_expected)
491 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
492 self.assertEqual(obj.expl_tag, expl or expl_initial)
495 default_initial if default is None else default,
497 if obj.default is None:
498 optional = optional_initial if optional is None else optional
499 optional = False if optional is None else optional
502 self.assertEqual(obj.optional, optional)
504 @given(boolean_values_strategy())
505 def test_copy(self, values):
506 for klass in (Boolean, BooleanInherited):
508 for copy_func in copy_funcs:
509 obj_copied = copy_func(obj)
510 self.assert_copied_basic_fields(obj, obj_copied)
514 integers(min_value=1).map(tag_encode),
516 def test_stripped(self, value, tag_impl):
517 obj = Boolean(value, impl=tag_impl)
518 with self.assertRaises(NotEnoughData):
519 obj.decode(obj.encode()[:-1])
520 with self.assertRaises(NotEnoughData):
521 obj.decode(encode2pass(obj)[:-1])
525 integers(min_value=1).map(tag_ctxc),
527 def test_stripped_expl(self, value, tag_expl):
528 obj = Boolean(value, expl=tag_expl)
529 with self.assertRaises(NotEnoughData):
530 obj.decode(obj.encode()[:-1])
531 with self.assertRaises(NotEnoughData):
532 obj.decode(encode2pass(obj)[:-1])
535 integers(min_value=31),
536 integers(min_value=0),
539 def test_bad_tag(self, tag, offset, decode_path):
540 with self.assertRaises(DecodeError) as err:
542 tag_encode(tag)[:-1],
544 decode_path=decode_path,
547 self.assertEqual(err.exception.offset, offset)
548 self.assertEqual(err.exception.decode_path, decode_path)
551 integers(min_value=31),
552 integers(min_value=0),
555 def test_bad_expl_tag(self, tag, offset, decode_path):
556 with self.assertRaises(DecodeError) as err:
557 Boolean(expl=Boolean.tag_default).decode(
558 tag_encode(tag)[:-1],
560 decode_path=decode_path,
563 self.assertEqual(err.exception.offset, offset)
564 self.assertEqual(err.exception.decode_path, decode_path)
567 integers(min_value=128),
568 integers(min_value=0),
571 def test_bad_len(self, l, offset, decode_path):
572 with self.assertRaises(DecodeError) as err:
574 Boolean.tag_default + len_encode(l)[:-1],
576 decode_path=decode_path,
579 self.assertEqual(err.exception.offset, offset)
580 self.assertEqual(err.exception.decode_path, decode_path)
583 integers(min_value=128),
584 integers(min_value=0),
587 def test_bad_expl_len(self, l, offset, decode_path):
588 with self.assertRaises(DecodeError) as err:
589 Boolean(expl=Boolean.tag_default).decode(
590 Boolean.tag_default + len_encode(l)[:-1],
592 decode_path=decode_path,
595 self.assertEqual(err.exception.offset, offset)
596 self.assertEqual(err.exception.decode_path, decode_path)
598 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
600 boolean_values_strategy(),
602 integers(min_value=1).map(tag_ctxc),
603 integers(min_value=0),
607 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
608 for klass in (Boolean, BooleanInherited):
609 _, _, _, default, optional, _decoded = values
618 pprint(obj, big_blobs=True, with_decode_path=True)
619 self.assertFalse(obj.expled)
620 obj_encoded = obj.encode()
621 self.assertEqual(encode2pass(obj), obj_encoded)
622 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
623 obj_expled = obj(value, expl=tag_expl)
624 self.assertTrue(obj_expled.expled)
626 list(obj_expled.pps())
627 pprint(obj_expled, big_blobs=True, with_decode_path=True)
628 obj_expled_cer = encode_cer(obj_expled)
629 self.assertNotEqual(obj_expled_cer, obj_encoded)
630 self.assertSequenceEqual(
631 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
634 obj_expled_hex_encoded = obj_expled.hexencode()
635 ctx_copied = deepcopy(ctx_dummy)
636 obj_decoded, tail = obj_expled.hexdecode(
637 obj_expled_hex_encoded + hexenc(tail_junk),
641 self.assertDictEqual(ctx_copied, ctx_dummy)
643 list(obj_decoded.pps())
644 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
645 self.assertEqual(tail, tail_junk)
646 self.assertEqual(obj_decoded, obj_expled)
647 self.assertNotEqual(obj_decoded, obj)
648 self.assertEqual(bool(obj_decoded), bool(obj_expled))
649 self.assertEqual(bool(obj_decoded), bool(obj))
650 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
651 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
652 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
654 obj_decoded.expl_llen,
655 len(len_encode(len(obj_encoded))),
657 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
658 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
661 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
663 self.assertEqual(obj_decoded.expl_offset, offset)
664 assert_exceeding_data(
666 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
670 evgens = list(obj_expled.decode_evgen(
671 hexdec(obj_expled_hex_encoded) + tail_junk,
673 decode_path=decode_path,
676 self.assertEqual(len(evgens), 1)
677 _decode_path, obj, tail = evgens[0]
678 self.assertSequenceEqual(tail, tail_junk)
679 self.assertEqual(_decode_path, decode_path)
680 self.assertEqual(obj, obj_decoded)
681 self.assertEqual(obj.expl_offset, offset)
685 @given(integers(min_value=2))
686 def test_invalid_len(self, l):
687 with self.assertRaises(InvalidLength):
688 Boolean().decode(b"".join((
694 @given(integers(min_value=0 + 1, max_value=255 - 1))
695 def test_ber_value(self, value):
696 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
697 Boolean().decode(b"".join((
707 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
708 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
709 self.assertTrue(bool(obj))
710 self.assertTrue(obj.ber_encoded)
711 self.assertFalse(obj.lenindef)
712 self.assertTrue(obj.bered)
714 self.assertTrue(obj.ber_encoded)
715 self.assertFalse(obj.lenindef)
716 self.assertTrue(obj.bered)
719 integers(min_value=1).map(tag_ctxc),
720 binary().filter(lambda x: not x.startswith(EOC)),
722 def test_ber_expl_no_eoc(self, expl, junk):
723 encoded = expl + LENINDEF + Boolean(False).encode()
724 with self.assertRaises(LenIndefForm):
725 Boolean(expl=expl).decode(encoded + junk)
726 with assertRaisesRegex(self, DecodeError, "no EOC"):
727 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
728 obj, tail = Boolean(expl=expl).decode(
729 encoded + EOC + junk,
732 self.assertTrue(obj.expl_lenindef)
733 self.assertFalse(obj.lenindef)
734 self.assertFalse(obj.ber_encoded)
735 self.assertTrue(obj.bered)
737 self.assertTrue(obj.expl_lenindef)
738 self.assertFalse(obj.lenindef)
739 self.assertFalse(obj.ber_encoded)
740 self.assertTrue(obj.bered)
741 self.assertSequenceEqual(tail, junk)
744 pprint(obj, big_blobs=True, with_decode_path=True)
747 integers(min_value=1).map(tag_ctxc),
754 def test_ber_expl(self, expl, values):
760 Boolean(value).encode() +
763 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
765 class SeqOf(SequenceOf):
766 schema = Boolean(expl=expl)
767 with self.assertRaises(LenIndefForm):
768 SeqOf().decode(encoded)
769 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
770 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
771 self.assertSequenceEqual(tail, b"")
772 self.assertSequenceEqual([bool(v) for v in seqof], values)
788 len(expl) + 1 + 3 + EOC_LEN,
799 pprint(seqof, big_blobs=True, with_decode_path=True)
803 def integer_values_strategy(draw, do_expl=False):
804 bound_min, value, default, bound_max = sorted(draw(sets(
813 _specs = draw(sets(text_letters()))
816 min_size=len(_specs),
817 max_size=len(_specs),
819 _specs = list(zip(_specs, values))
822 bounds = (bound_min, bound_max)
826 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
828 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
831 optional = draw(one_of(none(), booleans()))
833 draw(integers(min_value=0)),
834 draw(integers(min_value=0)),
835 draw(integers(min_value=0)),
837 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
840 class IntegerInherited(Integer):
844 class TestInteger(CommonMixin, TestCase):
847 def test_invalid_value_type(self):
848 with self.assertRaises(InvalidValueType) as err:
852 @given(sets(text_letters(), min_size=2))
853 def test_unknown_name(self, names_input):
854 missing = names_input.pop()
857 schema = [(n, 123) for n in names_input]
858 with self.assertRaises(ObjUnknown) as err:
862 @given(sets(text_letters(), min_size=2))
863 def test_known_name(self, names_input):
865 schema = [(n, 123) for n in names_input]
866 Int(names_input.pop())
869 def test_optional(self, optional):
870 obj = Integer(default=Integer(0), optional=optional)
871 self.assertTrue(obj.optional)
874 def test_ready(self, value):
876 self.assertFalse(obj.ready)
879 pprint(obj, big_blobs=True, with_decode_path=True)
880 with self.assertRaises(ObjNotReady) as err:
882 with self.assertRaises(ObjNotReady) as err:
886 self.assertTrue(obj.ready)
889 pprint(obj, big_blobs=True, with_decode_path=True)
892 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
893 def test_comparison(self, value1, value2, tag1, tag2):
894 for klass in (Integer, IntegerInherited):
897 self.assertEqual(obj1 == obj2, value1 == value2)
898 self.assertEqual(obj1 != obj2, value1 != value2)
899 self.assertEqual(obj1 == int(obj2), value1 == value2)
900 obj1 = klass(value1, impl=tag1)
901 obj2 = klass(value1, impl=tag2)
902 self.assertEqual(obj1 == obj2, tag1 == tag2)
903 self.assertEqual(obj1 != obj2, tag1 != tag2)
905 @given(lists(integers()))
906 def test_sorted_works(self, values):
907 self.assertSequenceEqual(
908 [int(v) for v in sorted(Integer(v) for v in values)],
912 @given(data_strategy())
913 def test_named(self, d):
914 names_input = list(d.draw(sets(text_letters(), min_size=1)))
915 values_input = list(d.draw(sets(
917 min_size=len(names_input),
918 max_size=len(names_input),
920 chosen_name = d.draw(sampled_from(names_input))
921 names_input = dict(zip(names_input, values_input))
925 _int = Int(chosen_name)
926 self.assertEqual(_int.named, chosen_name)
927 self.assertEqual(int(_int), names_input[chosen_name])
929 @given(integers(), integers(min_value=0), integers(min_value=0))
930 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
931 value = bound_min + value_delta
932 bound_max = value + bound_delta
933 Integer(value=value, bounds=(bound_min, bound_max))
935 @given(sets(integers(), min_size=3, max_size=3))
936 def test_bounds_unsatisfied(self, values):
937 values = sorted(values)
938 with self.assertRaises(BoundsError) as err:
939 Integer(value=values[0], bounds=(values[1], values[2]))
941 with assertRaisesRegex(self, DecodeError, "bounds") as err:
942 Integer(bounds=(values[1], values[2])).decode(
943 Integer(values[0]).encode()
946 with assertRaisesRegex(self, DecodeError, "bounds") as err:
947 Integer(bounds=(values[1], values[2])).decode(
948 encode2pass(Integer(values[0]))
950 with self.assertRaises(BoundsError) as err:
951 Integer(value=values[2], bounds=(values[0], values[1]))
953 with assertRaisesRegex(self, DecodeError, "bounds") as err:
954 Integer(bounds=(values[0], values[1])).decode(
955 Integer(values[2]).encode()
958 with assertRaisesRegex(self, DecodeError, "bounds") as err:
959 Integer(bounds=(values[0], values[1])).decode(
960 encode2pass(Integer(values[2]))
963 @given(data_strategy())
964 def test_call(self, d):
965 for klass in (Integer, IntegerInherited):
975 ) = d.draw(integer_values_strategy())
982 optional_initial or False,
995 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
996 if (default is None) and (obj_initial.default is not None):
1000 (value is not None) and
1001 (bounds_initial is not None) and
1002 not (bounds_initial[0] <= value <= bounds_initial[1])
1006 (bounds is None) and
1007 (default is not None) and
1008 (bounds_initial is not None) and
1009 not (bounds_initial[0] <= default <= bounds_initial[1])
1012 obj = obj_initial(value, bounds, impl, expl, default, optional)
1014 value_expected = default if value is None else value
1016 default_initial if value_expected is None
1019 self.assertEqual(obj, value_expected)
1020 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1021 self.assertEqual(obj.expl_tag, expl or expl_initial)
1024 default_initial if default is None else default,
1026 if obj.default is None:
1027 optional = optional_initial if optional is None else optional
1028 optional = False if optional is None else optional
1031 self.assertEqual(obj.optional, optional)
1033 (obj._bound_min, obj._bound_max),
1034 bounds or bounds_initial or (float("-inf"), float("+inf")),
1038 {} if _specs_initial is None else dict(_specs_initial),
1041 @given(integer_values_strategy())
1042 def test_copy(self, values):
1043 for klass in (Integer, IntegerInherited):
1044 obj = klass(*values)
1045 for copy_func in copy_funcs:
1046 obj_copied = copy_func(obj)
1047 self.assert_copied_basic_fields(obj, obj_copied)
1048 self.assertEqual(obj.specs, obj_copied.specs)
1049 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1050 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1051 self.assertEqual(obj._value, obj_copied._value)
1055 integers(min_value=1).map(tag_encode),
1057 def test_stripped(self, value, tag_impl):
1058 obj = Integer(value, impl=tag_impl)
1059 with self.assertRaises(NotEnoughData):
1060 obj.decode(obj.encode()[:-1])
1064 integers(min_value=1).map(tag_ctxc),
1066 def test_stripped_expl(self, value, tag_expl):
1067 obj = Integer(value, expl=tag_expl)
1068 with self.assertRaises(NotEnoughData):
1069 obj.decode(obj.encode()[:-1])
1071 def test_zero_len(self):
1072 with self.assertRaises(NotEnoughData):
1073 Integer().decode(b"".join((
1074 Integer.tag_default,
1079 integers(min_value=31),
1080 integers(min_value=0),
1083 def test_bad_tag(self, tag, offset, decode_path):
1084 with self.assertRaises(DecodeError) as err:
1086 tag_encode(tag)[:-1],
1088 decode_path=decode_path,
1091 self.assertEqual(err.exception.offset, offset)
1092 self.assertEqual(err.exception.decode_path, decode_path)
1095 integers(min_value=128),
1096 integers(min_value=0),
1099 def test_bad_len(self, l, offset, decode_path):
1100 with self.assertRaises(DecodeError) as err:
1102 Integer.tag_default + len_encode(l)[:-1],
1104 decode_path=decode_path,
1107 self.assertEqual(err.exception.offset, offset)
1108 self.assertEqual(err.exception.decode_path, decode_path)
1111 sets(integers(), min_size=2, max_size=2),
1112 integers(min_value=0),
1115 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1116 value, bound_min = list(sorted(ints))
1119 bounds = (bound_min, bound_min)
1120 with self.assertRaises(DecodeError) as err:
1122 Integer(value).encode(),
1124 decode_path=decode_path,
1127 self.assertEqual(err.exception.offset, offset)
1128 self.assertEqual(err.exception.decode_path, decode_path)
1130 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1132 integer_values_strategy(),
1134 integers(min_value=1).map(tag_ctxc),
1135 integers(min_value=0),
1139 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1140 for klass in (Integer, IntegerInherited):
1141 _, _, _, _, default, optional, _, _decoded = values
1150 pprint(obj, big_blobs=True, with_decode_path=True)
1151 self.assertFalse(obj.expled)
1152 obj_encoded = obj.encode()
1153 self.assertEqual(encode2pass(obj), obj_encoded)
1154 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1155 obj_expled = obj(value, expl=tag_expl)
1156 self.assertTrue(obj_expled.expled)
1158 list(obj_expled.pps())
1159 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1160 obj_expled_encoded = obj_expled.encode()
1161 obj_expled_cer = encode_cer(obj_expled)
1162 self.assertNotEqual(obj_expled_cer, obj_encoded)
1163 self.assertSequenceEqual(
1164 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1167 ctx_copied = deepcopy(ctx_dummy)
1168 obj_decoded, tail = obj_expled.decode(
1169 obj_expled_encoded + tail_junk,
1173 self.assertDictEqual(ctx_copied, ctx_dummy)
1175 list(obj_decoded.pps())
1176 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1177 self.assertEqual(tail, tail_junk)
1178 self.assertEqual(obj_decoded, obj_expled)
1179 self.assertNotEqual(obj_decoded, obj)
1180 self.assertEqual(int(obj_decoded), int(obj_expled))
1181 self.assertEqual(int(obj_decoded), int(obj))
1182 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1183 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1184 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1186 obj_decoded.expl_llen,
1187 len(len_encode(len(obj_encoded))),
1189 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1190 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1193 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1195 self.assertEqual(obj_decoded.expl_offset, offset)
1196 assert_exceeding_data(
1198 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1202 evgens = list(obj_expled.decode_evgen(
1203 obj_expled_encoded + tail_junk,
1205 decode_path=decode_path,
1208 self.assertEqual(len(evgens), 1)
1209 _decode_path, obj, tail = evgens[0]
1210 self.assertSequenceEqual(tail, tail_junk)
1211 self.assertEqual(_decode_path, decode_path)
1212 self.assertEqual(obj, obj_decoded)
1213 self.assertEqual(obj.expl_offset, offset)
1217 def test_go_vectors_valid(self):
1218 for data, expect in ((
1222 (b"\xff\x7f", -129),
1226 (b"\xff\x00", -256),
1230 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1231 (b"\x80\x00\x00\x00", -2147483648),
1234 Integer().decode(b"".join((
1235 Integer.tag_default,
1236 len_encode(len(data)),
1242 def test_go_vectors_invalid(self):
1247 with self.assertRaises(DecodeError):
1248 Integer().decode(b"".join((
1249 Integer.tag_default,
1250 len_encode(len(data)),
1256 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1259 if draw(booleans()):
1260 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1262 integers(min_value=0, max_value=255),
1263 min_size=len(schema),
1264 max_size=len(schema),
1266 schema = list(zip(schema, bits))
1268 def _value(value_required):
1269 if not value_required and draw(booleans()):
1271 generation_choice = 0
1273 generation_choice = draw(sampled_from((1, 2, 3)))
1274 if generation_choice == 1 or draw(booleans()):
1275 return "'%s'B" % "".join(draw(lists(
1276 sampled_from(("0", "1")),
1277 max_size=len(schema),
1279 if generation_choice == 2 or draw(booleans()):
1280 return draw(binary(max_size=len(schema) // 8))
1281 if generation_choice == 3 or draw(booleans()):
1282 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1284 value = _value(value_required)
1285 default = _value(value_required=False)
1289 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1291 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1292 optional = draw(one_of(none(), booleans()))
1294 draw(integers(min_value=0)),
1295 draw(integers(min_value=0)),
1296 draw(integers(min_value=0)),
1298 return (schema, value, impl, expl, default, optional, _decoded)
1301 class BitStringInherited(BitString):
1305 class TestBitString(CommonMixin, TestCase):
1306 base_klass = BitString
1308 @given(lists(booleans()))
1309 def test_b_encoding(self, bits):
1310 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1311 self.assertEqual(obj.bit_len, len(bits))
1312 self.assertSequenceEqual(list(obj), bits)
1313 for i, bit in enumerate(bits):
1314 self.assertEqual(obj[i], bit)
1316 @given(lists(booleans()))
1317 def test_out_of_bounds_bits(self, bits):
1318 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1319 for i in range(len(bits), len(bits) * 2):
1320 self.assertFalse(obj[i])
1322 def test_bad_b_encoding(self):
1323 with self.assertRaises(ValueError):
1324 BitString("'010120101'B")
1327 integers(min_value=1, max_value=255),
1328 integers(min_value=1, max_value=255),
1330 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1331 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1332 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1333 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1335 class BS(BitString):
1336 schema = (("whatever", 0),)
1337 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1338 self.assertEqual(obj.bit_len, leading_zeros + 1)
1339 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1341 def test_zero_len(self):
1342 with self.assertRaises(NotEnoughData):
1343 BitString().decode(b"".join((
1344 BitString.tag_default,
1348 def test_invalid_value_type(self):
1349 with self.assertRaises(InvalidValueType) as err:
1352 with self.assertRaises(InvalidValueType) as err:
1356 def test_obj_unknown(self):
1357 with self.assertRaises(ObjUnknown) as err:
1358 BitString(b"whatever")["whenever"]
1361 def test_get_invalid_type(self):
1362 with self.assertRaises(InvalidValueType) as err:
1363 BitString(b"whatever")[(1, 2, 3)]
1366 @given(data_strategy())
1367 def test_unknown_name(self, d):
1368 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1369 missing = _schema.pop()
1371 class BS(BitString):
1372 schema = [(n, i) for i, n in enumerate(_schema)]
1373 with self.assertRaises(ObjUnknown) as err:
1378 def test_optional(self, optional):
1379 obj = BitString(default=BitString(b""), optional=optional)
1380 self.assertTrue(obj.optional)
1383 def test_ready(self, value):
1385 self.assertFalse(obj.ready)
1388 pprint(obj, big_blobs=True, with_decode_path=True)
1389 with self.assertRaises(ObjNotReady) as err:
1392 with self.assertRaises(ObjNotReady) as err:
1394 obj = BitString(value)
1395 self.assertTrue(obj.ready)
1398 pprint(obj, big_blobs=True, with_decode_path=True)
1401 tuples(integers(min_value=0), binary()),
1402 tuples(integers(min_value=0), binary()),
1406 def test_comparison(self, value1, value2, tag1, tag2):
1407 for klass in (BitString, BitStringInherited):
1408 obj1 = klass(value1)
1409 obj2 = klass(value2)
1410 self.assertEqual(obj1 == obj2, value1 == value2)
1411 self.assertEqual(obj1 != obj2, value1 != value2)
1412 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1413 obj1 = klass(value1, impl=tag1)
1414 obj2 = klass(value1, impl=tag2)
1415 self.assertEqual(obj1 == obj2, tag1 == tag2)
1416 self.assertEqual(obj1 != obj2, tag1 != tag2)
1418 @given(data_strategy())
1419 def test_call(self, d):
1420 for klass in (BitString, BitStringInherited):
1429 ) = d.draw(bit_string_values_strategy())
1432 schema = schema_initial
1434 value=value_initial,
1437 default=default_initial,
1438 optional=optional_initial or False,
1439 _decoded=_decoded_initial,
1449 ) = d.draw(bit_string_values_strategy(
1450 schema=schema_initial,
1451 do_expl=impl_initial is None,
1460 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1461 self.assertEqual(obj.expl_tag, expl or expl_initial)
1462 if obj.default is None:
1463 optional = optional_initial if optional is None else optional
1464 optional = False if optional is None else optional
1467 self.assertEqual(obj.optional, optional)
1468 self.assertEqual(obj.specs, obj_initial.specs)
1470 @given(bit_string_values_strategy())
1471 def test_copy(self, values):
1472 for klass in (BitString, BitStringInherited):
1473 _schema, value, impl, expl, default, optional, _decoded = values
1483 optional=optional or False,
1486 for copy_func in copy_funcs:
1487 obj_copied = copy_func(obj)
1488 self.assert_copied_basic_fields(obj, obj_copied)
1489 self.assertEqual(obj.specs, obj_copied.specs)
1490 self.assertEqual(obj._value, obj_copied._value)
1494 integers(min_value=1).map(tag_encode),
1496 def test_stripped(self, value, tag_impl):
1497 obj = BitString(value, impl=tag_impl)
1498 with self.assertRaises(NotEnoughData):
1499 obj.decode(obj.encode()[:-1])
1503 integers(min_value=1).map(tag_ctxc),
1505 def test_stripped_expl(self, value, tag_expl):
1506 obj = BitString(value, expl=tag_expl)
1507 with self.assertRaises(NotEnoughData):
1508 obj.decode(obj.encode()[:-1])
1511 integers(min_value=31),
1512 integers(min_value=0),
1515 def test_bad_tag(self, tag, offset, decode_path):
1516 with self.assertRaises(DecodeError) as err:
1518 tag_encode(tag)[:-1],
1520 decode_path=decode_path,
1523 self.assertEqual(err.exception.offset, offset)
1524 self.assertEqual(err.exception.decode_path, decode_path)
1527 integers(min_value=128),
1528 integers(min_value=0),
1531 def test_bad_len(self, l, offset, decode_path):
1532 with self.assertRaises(DecodeError) as err:
1534 BitString.tag_default + len_encode(l)[:-1],
1536 decode_path=decode_path,
1539 self.assertEqual(err.exception.offset, offset)
1540 self.assertEqual(err.exception.decode_path, decode_path)
1542 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1543 @given(data_strategy())
1544 def test_symmetric(self, d):
1553 ) = d.draw(bit_string_values_strategy(value_required=True))
1554 tail_junk = d.draw(binary(max_size=5))
1555 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1556 offset = d.draw(integers(min_value=0))
1557 decode_path = d.draw(decode_path_strat)
1558 for klass in (BitString, BitStringInherited):
1569 pprint(obj, big_blobs=True, with_decode_path=True)
1570 self.assertFalse(obj.expled)
1571 obj_encoded = obj.encode()
1572 self.assertEqual(encode2pass(obj), obj_encoded)
1573 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1574 obj_expled = obj(value, expl=tag_expl)
1575 self.assertTrue(obj_expled.expled)
1577 list(obj_expled.pps())
1578 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1579 obj_expled_encoded = obj_expled.encode()
1580 obj_expled_cer = encode_cer(obj_expled)
1581 self.assertNotEqual(obj_expled_cer, obj_encoded)
1582 self.assertSequenceEqual(
1583 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1586 ctx_copied = deepcopy(ctx_dummy)
1587 obj_decoded, tail = obj_expled.decode(
1588 obj_expled_encoded + tail_junk,
1592 self.assertDictEqual(ctx_copied, ctx_dummy)
1594 list(obj_decoded.pps())
1595 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1596 self.assertEqual(tail, tail_junk)
1597 self.assertEqual(obj_decoded, obj_expled)
1598 self.assertNotEqual(obj_decoded, obj)
1599 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1600 self.assertEqual(bytes(obj_decoded), bytes(obj))
1601 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1602 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1603 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1605 obj_decoded.expl_llen,
1606 len(len_encode(len(obj_encoded))),
1608 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1609 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1612 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1614 self.assertEqual(obj_decoded.expl_offset, offset)
1615 if isinstance(value, tuple):
1616 self.assertSetEqual(set(value), set(obj_decoded.named))
1619 assert_exceeding_data(
1621 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1625 evgens = list(obj_expled.decode_evgen(
1626 obj_expled_encoded + tail_junk,
1628 decode_path=decode_path,
1631 self.assertEqual(len(evgens), 1)
1632 _decode_path, obj, tail = evgens[0]
1633 self.assertSequenceEqual(tail, tail_junk)
1634 self.assertEqual(_decode_path, decode_path)
1635 self.assertEqual(obj.expl_offset, offset)
1639 @given(integers(min_value=1, max_value=255))
1640 def test_bad_zero_value(self, pad_size):
1641 with self.assertRaises(DecodeError):
1642 BitString().decode(b"".join((
1643 BitString.tag_default,
1648 def test_go_vectors_invalid(self):
1654 with self.assertRaises(DecodeError):
1655 BitString().decode(b"".join((
1656 BitString.tag_default,
1661 def test_go_vectors_valid(self):
1662 obj, _ = BitString().decode(b"".join((
1663 BitString.tag_default,
1667 self.assertEqual(bytes(obj), b"")
1668 self.assertEqual(obj.bit_len, 0)
1670 obj, _ = BitString().decode(b"".join((
1671 BitString.tag_default,
1675 self.assertEqual(bytes(obj), b"\x00")
1676 self.assertEqual(obj.bit_len, 1)
1678 obj = BitString((16, b"\x82\x40"))
1679 self.assertTrue(obj[0])
1680 self.assertFalse(obj[1])
1681 self.assertTrue(obj[6])
1682 self.assertTrue(obj[9])
1683 self.assertFalse(obj[17])
1685 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1687 integers(min_value=1, max_value=30),
1690 binary(min_size=1, max_size=5),
1692 binary(min_size=1, max_size=5),
1700 lists(booleans(), min_size=1),
1704 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1705 def chunk_constructed(contents):
1707 tag_encode(form=TagFormConstructed, num=3) +
1709 b"".join(BitString(content).encode() for content in contents) +
1713 chunks_len_expected = []
1714 payload_expected = b""
1715 bit_len_expected = 0
1716 for chunk_input in chunk_inputs:
1717 if isinstance(chunk_input, binary_type):
1718 chunks.append(BitString(chunk_input).encode())
1719 payload_expected += chunk_input
1720 bit_len_expected += len(chunk_input) * 8
1721 chunks_len_expected.append(len(chunk_input) + 1)
1723 chunks.append(chunk_constructed(chunk_input))
1724 payload = b"".join(chunk_input)
1725 payload_expected += payload
1726 bit_len_expected += len(payload) * 8
1727 for c in chunk_input:
1728 chunks_len_expected.append(len(c) + 1)
1729 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1730 chunk_last = BitString("'%s'B" % "".join(
1731 "1" if bit else "0" for bit in chunk_last_bits
1733 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1734 payload_expected += bytes(chunk_last)
1735 bit_len_expected += chunk_last.bit_len
1736 encoded_indefinite = (
1737 tag_encode(form=TagFormConstructed, num=impl) +
1740 chunk_last.encode() +
1743 encoded_definite = (
1744 tag_encode(form=TagFormConstructed, num=impl) +
1745 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1749 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1750 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1751 for lenindef_expected, encoded in (
1752 (True, encoded_indefinite),
1753 (False, encoded_definite),
1755 obj, tail = BitString(impl=tag_encode(impl)).decode(
1757 ctx={"bered": True},
1759 self.assertSequenceEqual(tail, junk)
1760 self.assertEqual(obj.bit_len, bit_len_expected)
1761 self.assertSequenceEqual(bytes(obj), payload_expected)
1762 self.assertTrue(obj.ber_encoded)
1763 self.assertEqual(obj.lenindef, lenindef_expected)
1764 self.assertTrue(obj.bered)
1766 self.assertTrue(obj.ber_encoded)
1767 self.assertEqual(obj.lenindef, lenindef_expected)
1768 self.assertTrue(obj.bered)
1769 self.assertEqual(len(encoded), obj.tlvlen)
1772 pprint(obj, big_blobs=True, with_decode_path=True)
1774 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1776 decode_path=decode_path,
1777 ctx={"bered": True},
1779 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1780 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1781 self.assertGreater(len(dp), len(decode_path))
1782 self.assertEqual(obj.vlen, chunk_len_expected)
1785 integers(min_value=0),
1788 def test_ber_definite_too_short(self, offset, decode_path):
1789 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1791 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1793 decode_path=decode_path,
1794 ctx={"bered": True},
1796 self.assertEqual(err.exception.decode_path, decode_path)
1797 self.assertEqual(err.exception.offset, offset)
1800 integers(min_value=0),
1803 def test_ber_definite_no_data(self, offset, decode_path):
1804 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1806 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1808 decode_path=decode_path,
1809 ctx={"bered": True},
1811 self.assertEqual(err.exception.decode_path, decode_path)
1812 self.assertEqual(err.exception.offset, offset)
1815 integers(min_value=0),
1817 integers(min_value=1, max_value=3),
1819 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1820 bs = BitString(b"data").encode()
1821 with self.assertRaises(NotEnoughData) as err:
1823 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1825 decode_path=decode_path,
1826 ctx={"bered": True},
1828 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1829 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1832 integers(min_value=0),
1834 integers(min_value=1, max_value=3),
1836 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1837 bs = BitString(b"data").encode()
1838 bs_longer = BitString(b"data-longer").encode()
1839 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1842 tag_encode(3, form=TagFormConstructed) +
1843 len_encode((chunks + 1) * len(bs)) +
1848 decode_path=decode_path,
1849 ctx={"bered": True},
1851 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1852 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1855 integers(min_value=0),
1858 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1859 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1861 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1863 decode_path=decode_path,
1864 ctx={"bered": True},
1866 self.assertEqual(err.exception.decode_path, decode_path)
1867 self.assertEqual(err.exception.offset, offset)
1869 @given(data_strategy())
1870 def test_ber_indefinite_not_multiple(self, d):
1871 bs_short = BitString("'A'H").encode()
1872 bs_full = BitString("'AA'H").encode()
1873 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1874 chunks.append(bs_short)
1875 d.draw(permutations(chunks))
1876 chunks.append(bs_short)
1877 offset = d.draw(integers(min_value=0))
1878 decode_path = d.draw(decode_path_strat)
1879 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1882 tag_encode(3, form=TagFormConstructed) +
1888 decode_path=decode_path,
1889 ctx={"bered": True},
1892 err.exception.decode_path,
1893 decode_path + (str(chunks.index(bs_short)),),
1896 err.exception.offset,
1897 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1900 def test_x690_vector(self):
1901 vector = BitString("'0A3B5F291CD'H")
1902 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1903 self.assertSequenceEqual(tail, b"")
1904 self.assertEqual(obj, vector)
1905 obj, tail = BitString().decode(
1906 hexdec("23800303000A3B0305045F291CD00000"),
1907 ctx={"bered": True},
1909 self.assertSequenceEqual(tail, b"")
1910 self.assertEqual(obj, vector)
1911 self.assertTrue(obj.ber_encoded)
1912 self.assertTrue(obj.lenindef)
1913 self.assertTrue(obj.bered)
1915 self.assertTrue(obj.ber_encoded)
1916 self.assertTrue(obj.lenindef)
1917 self.assertTrue(obj.bered)
1919 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1920 @given(integers(min_value=1000, max_value=3000))
1921 def test_cer(self, data_len):
1922 data = urandom(data_len)
1923 encoded = encode_cer(BitString(data))
1924 ctx = {"bered": True}
1925 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1926 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1927 evgens_expected = data_len // 999
1928 if evgens_expected * 999 != data_len:
1929 evgens_expected += 1
1930 evgens_expected += 1
1931 self.assertEqual(len(evgens), evgens_expected)
1932 for (_, obj, _) in evgens[:-2]:
1933 self.assertEqual(obj.vlen, 1000)
1934 _, obj, _ = evgens[-2]
1935 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1939 def octet_string_values_strategy(draw, do_expl=False):
1940 bound_min, bound_max = sorted(draw(sets(
1941 integers(min_value=0, max_value=1 << 7),
1945 value = draw(one_of(
1947 binary(min_size=bound_min, max_size=bound_max),
1949 default = draw(one_of(
1951 binary(min_size=bound_min, max_size=bound_max),
1954 if draw(booleans()):
1955 bounds = (bound_min, bound_max)
1959 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1961 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1962 optional = draw(one_of(none(), booleans()))
1964 draw(integers(min_value=0)),
1965 draw(integers(min_value=0)),
1966 draw(integers(min_value=0)),
1968 return (value, bounds, impl, expl, default, optional, _decoded)
1971 class OctetStringInherited(OctetString):
1975 class TestOctetString(CommonMixin, TestCase):
1976 base_klass = OctetString
1978 def test_invalid_value_type(self):
1979 with self.assertRaises(InvalidValueType) as err:
1980 OctetString(text_type(123))
1984 def test_optional(self, optional):
1985 obj = OctetString(default=OctetString(b""), optional=optional)
1986 self.assertTrue(obj.optional)
1989 def test_ready(self, value):
1991 self.assertFalse(obj.ready)
1994 pprint(obj, big_blobs=True, with_decode_path=True)
1995 with self.assertRaises(ObjNotReady) as err:
1998 with self.assertRaises(ObjNotReady) as err:
2000 obj = OctetString(value)
2001 self.assertTrue(obj.ready)
2004 pprint(obj, big_blobs=True, with_decode_path=True)
2006 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2007 def test_comparison(self, value1, value2, tag1, tag2):
2008 for klass in (OctetString, OctetStringInherited):
2009 obj1 = klass(value1)
2010 obj2 = klass(value2)
2011 self.assertEqual(obj1 == obj2, value1 == value2)
2012 self.assertEqual(obj1 != obj2, value1 != value2)
2013 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2014 obj1 = klass(value1, impl=tag1)
2015 obj2 = klass(value1, impl=tag2)
2016 self.assertEqual(obj1 == obj2, tag1 == tag2)
2017 self.assertEqual(obj1 != obj2, tag1 != tag2)
2019 @given(lists(binary()))
2020 def test_sorted_works(self, values):
2021 self.assertSequenceEqual(
2022 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2026 @given(data_strategy())
2027 def test_bounds_satisfied(self, d):
2028 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2029 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2030 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2031 OctetString(value=value, bounds=(bound_min, bound_max))
2033 @given(data_strategy())
2034 def test_bounds_unsatisfied(self, d):
2035 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2036 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2037 value = d.draw(binary(max_size=bound_min - 1))
2038 with self.assertRaises(BoundsError) as err:
2039 OctetString(value=value, bounds=(bound_min, bound_max))
2041 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2042 OctetString(bounds=(bound_min, bound_max)).decode(
2043 OctetString(value).encode()
2046 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2047 OctetString(bounds=(bound_min, bound_max)).decode(
2048 encode2pass(OctetString(value))
2050 value = d.draw(binary(min_size=bound_max + 1))
2051 with self.assertRaises(BoundsError) as err:
2052 OctetString(value=value, bounds=(bound_min, bound_max))
2054 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2055 OctetString(bounds=(bound_min, bound_max)).decode(
2056 OctetString(value).encode()
2059 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2060 OctetString(bounds=(bound_min, bound_max)).decode(
2061 encode2pass(OctetString(value))
2064 @given(data_strategy())
2065 def test_call(self, d):
2066 for klass in (OctetString, OctetStringInherited):
2075 ) = d.draw(octet_string_values_strategy())
2076 obj_initial = klass(
2082 optional_initial or False,
2093 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2094 if (default is None) and (obj_initial.default is not None):
2097 (bounds is None) and
2098 (value is not None) and
2099 (bounds_initial is not None) and
2100 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2104 (bounds is None) and
2105 (default is not None) and
2106 (bounds_initial is not None) and
2107 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2110 obj = obj_initial(value, bounds, impl, expl, default, optional)
2112 value_expected = default if value is None else value
2114 default_initial if value_expected is None
2117 self.assertEqual(obj, value_expected)
2118 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2119 self.assertEqual(obj.expl_tag, expl or expl_initial)
2122 default_initial if default is None else default,
2124 if obj.default is None:
2125 optional = optional_initial if optional is None else optional
2126 optional = False if optional is None else optional
2129 self.assertEqual(obj.optional, optional)
2131 (obj._bound_min, obj._bound_max),
2132 bounds or bounds_initial or (0, float("+inf")),
2135 @given(octet_string_values_strategy())
2136 def test_copy(self, values):
2137 for klass in (OctetString, OctetStringInherited):
2138 obj = klass(*values)
2139 for copy_func in copy_funcs:
2140 obj_copied = copy_func(obj)
2141 self.assert_copied_basic_fields(obj, obj_copied)
2142 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2143 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2144 self.assertEqual(obj._value, obj_copied._value)
2148 integers(min_value=1).map(tag_encode),
2150 def test_stripped(self, value, tag_impl):
2151 obj = OctetString(value, impl=tag_impl)
2152 with self.assertRaises(NotEnoughData):
2153 obj.decode(obj.encode()[:-1])
2157 integers(min_value=1).map(tag_ctxc),
2159 def test_stripped_expl(self, value, tag_expl):
2160 obj = OctetString(value, expl=tag_expl)
2161 with self.assertRaises(NotEnoughData):
2162 obj.decode(obj.encode()[:-1])
2165 integers(min_value=31),
2166 integers(min_value=0),
2169 def test_bad_tag(self, tag, offset, decode_path):
2170 with self.assertRaises(DecodeError) as err:
2171 OctetString().decode(
2172 tag_encode(tag)[:-1],
2174 decode_path=decode_path,
2177 self.assertEqual(err.exception.offset, offset)
2178 self.assertEqual(err.exception.decode_path, decode_path)
2181 integers(min_value=128),
2182 integers(min_value=0),
2185 def test_bad_len(self, l, offset, decode_path):
2186 with self.assertRaises(DecodeError) as err:
2187 OctetString().decode(
2188 OctetString.tag_default + len_encode(l)[:-1],
2190 decode_path=decode_path,
2193 self.assertEqual(err.exception.offset, offset)
2194 self.assertEqual(err.exception.decode_path, decode_path)
2197 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2198 integers(min_value=0),
2201 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2202 value, bound_min = list(sorted(ints))
2204 class String(OctetString):
2205 bounds = (bound_min, bound_min)
2206 with self.assertRaises(DecodeError) as err:
2208 OctetString(b"\x00" * value).encode(),
2210 decode_path=decode_path,
2213 self.assertEqual(err.exception.offset, offset)
2214 self.assertEqual(err.exception.decode_path, decode_path)
2216 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2218 octet_string_values_strategy(),
2220 integers(min_value=1).map(tag_ctxc),
2221 integers(min_value=0),
2225 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2226 for klass in (OctetString, OctetStringInherited):
2227 _, _, _, _, default, optional, _decoded = values
2236 pprint(obj, big_blobs=True, with_decode_path=True)
2237 self.assertFalse(obj.expled)
2238 obj_encoded = obj.encode()
2239 self.assertEqual(encode2pass(obj), obj_encoded)
2240 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2241 obj_expled = obj(value, expl=tag_expl)
2242 self.assertTrue(obj_expled.expled)
2244 list(obj_expled.pps())
2245 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2246 obj_expled_encoded = obj_expled.encode()
2247 obj_expled_cer = encode_cer(obj_expled)
2248 self.assertNotEqual(obj_expled_cer, obj_encoded)
2249 self.assertSequenceEqual(
2250 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2253 ctx_copied = deepcopy(ctx_dummy)
2254 obj_decoded, tail = obj_expled.decode(
2255 obj_expled_encoded + tail_junk,
2259 self.assertDictEqual(ctx_copied, ctx_dummy)
2261 list(obj_decoded.pps())
2262 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2263 self.assertEqual(tail, tail_junk)
2264 self.assertEqual(obj_decoded, obj_expled)
2265 self.assertNotEqual(obj_decoded, obj)
2266 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2267 self.assertEqual(bytes(obj_decoded), bytes(obj))
2268 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2269 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2270 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2272 obj_decoded.expl_llen,
2273 len(len_encode(len(obj_encoded))),
2275 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2276 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2279 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2281 self.assertEqual(obj_decoded.expl_offset, offset)
2282 assert_exceeding_data(
2284 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2288 evgens = list(obj_expled.decode_evgen(
2289 obj_expled_encoded + tail_junk,
2291 decode_path=decode_path,
2294 self.assertEqual(len(evgens), 1)
2295 _decode_path, obj, tail = evgens[0]
2296 self.assertSequenceEqual(tail, tail_junk)
2297 self.assertEqual(_decode_path, decode_path)
2298 self.assertEqual(obj.expl_offset, offset)
2302 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2304 integers(min_value=1, max_value=30),
2307 binary(min_size=1, max_size=5),
2309 binary(min_size=1, max_size=5),
2320 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2321 def chunk_constructed(contents):
2323 tag_encode(form=TagFormConstructed, num=4) +
2325 b"".join(OctetString(content).encode() for content in contents) +
2329 chunks_len_expected = []
2330 payload_expected = b""
2331 for chunk_input in chunk_inputs:
2332 if isinstance(chunk_input, binary_type):
2333 chunks.append(OctetString(chunk_input).encode())
2334 payload_expected += chunk_input
2335 chunks_len_expected.append(len(chunk_input))
2337 chunks.append(chunk_constructed(chunk_input))
2338 payload = b"".join(chunk_input)
2339 payload_expected += payload
2340 for c in chunk_input:
2341 chunks_len_expected.append(len(c))
2342 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2343 encoded_indefinite = (
2344 tag_encode(form=TagFormConstructed, num=impl) +
2349 encoded_definite = (
2350 tag_encode(form=TagFormConstructed, num=impl) +
2351 len_encode(len(b"".join(chunks))) +
2354 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2355 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2356 for lenindef_expected, encoded in (
2357 (True, encoded_indefinite),
2358 (False, encoded_definite),
2360 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2362 ctx={"bered": True},
2364 self.assertSequenceEqual(tail, junk)
2365 self.assertSequenceEqual(bytes(obj), payload_expected)
2366 self.assertTrue(obj.ber_encoded)
2367 self.assertEqual(obj.lenindef, lenindef_expected)
2368 self.assertTrue(obj.bered)
2370 self.assertTrue(obj.ber_encoded)
2371 self.assertEqual(obj.lenindef, lenindef_expected)
2372 self.assertTrue(obj.bered)
2373 self.assertEqual(len(encoded), obj.tlvlen)
2376 pprint(obj, big_blobs=True, with_decode_path=True)
2378 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2380 decode_path=decode_path,
2381 ctx={"bered": True},
2383 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2384 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2385 self.assertGreater(len(dp), len(decode_path))
2386 self.assertEqual(obj.vlen, chunk_len_expected)
2389 integers(min_value=0),
2392 def test_ber_definite_too_short(self, offset, decode_path):
2393 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2394 OctetString().decode(
2395 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2397 decode_path=decode_path,
2398 ctx={"bered": True},
2400 self.assertEqual(err.exception.decode_path, decode_path)
2401 self.assertEqual(err.exception.offset, offset)
2404 integers(min_value=0),
2406 integers(min_value=1, max_value=3),
2408 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2409 bs = OctetString(b"data").encode()
2410 with self.assertRaises(NotEnoughData) as err:
2411 OctetString().decode(
2412 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2414 decode_path=decode_path,
2415 ctx={"bered": True},
2417 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2418 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2421 integers(min_value=0),
2423 integers(min_value=1, max_value=3),
2425 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2426 bs = OctetString(b"data").encode()
2427 bs_longer = OctetString(b"data-longer").encode()
2428 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2429 OctetString().decode(
2431 tag_encode(4, form=TagFormConstructed) +
2432 len_encode((chunks + 1) * len(bs)) +
2437 decode_path=decode_path,
2438 ctx={"bered": True},
2440 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2441 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2443 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2444 @given(integers(min_value=1001, max_value=3000))
2445 def test_cer(self, data_len):
2446 data = urandom(data_len)
2447 encoded = encode_cer(OctetString(data))
2448 ctx = {"bered": True}
2449 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2450 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2451 evgens_expected = data_len // 1000
2452 if evgens_expected * 1000 != data_len:
2453 evgens_expected += 1
2454 evgens_expected += 1
2455 self.assertEqual(len(evgens), evgens_expected)
2456 for (_, obj, _) in evgens[:-2]:
2457 self.assertEqual(obj.vlen, 1000)
2458 _, obj, _ = evgens[-2]
2459 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2463 def null_values_strategy(draw, do_expl=False):
2467 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2469 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2470 optional = draw(one_of(none(), booleans()))
2472 draw(integers(min_value=0)),
2473 draw(integers(min_value=0)),
2474 draw(integers(min_value=0)),
2476 return (impl, expl, optional, _decoded)
2479 class NullInherited(Null):
2483 class TestNull(CommonMixin, TestCase):
2486 def test_ready(self):
2488 self.assertTrue(obj.ready)
2491 pprint(obj, big_blobs=True, with_decode_path=True)
2493 @given(binary(min_size=1), binary(min_size=1))
2494 def test_comparison(self, tag1, tag2):
2495 for klass in (Null, NullInherited):
2496 obj1 = klass(impl=tag1)
2497 obj2 = klass(impl=tag2)
2498 self.assertEqual(obj1 == obj2, tag1 == tag2)
2499 self.assertEqual(obj1 != obj2, tag1 != tag2)
2500 self.assertNotEqual(obj1, tag2)
2502 @given(data_strategy())
2503 def test_call(self, d):
2504 for klass in (Null, NullInherited):
2510 ) = d.draw(null_values_strategy())
2511 obj_initial = klass(
2514 optional=optional_initial or False,
2515 _decoded=_decoded_initial,
2522 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2523 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2524 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2525 self.assertEqual(obj.expl_tag, expl or expl_initial)
2526 optional = optional_initial if optional is None else optional
2527 optional = False if optional is None else optional
2528 self.assertEqual(obj.optional, optional)
2530 @given(null_values_strategy())
2531 def test_copy(self, values):
2532 for klass in (Null, NullInherited):
2533 impl, expl, optional, _decoded = values
2537 optional=optional or False,
2540 for copy_func in copy_funcs:
2541 obj_copied = copy_func(obj)
2542 self.assert_copied_basic_fields(obj, obj_copied)
2544 @given(integers(min_value=1).map(tag_encode))
2545 def test_stripped(self, tag_impl):
2546 obj = Null(impl=tag_impl)
2547 with self.assertRaises(NotEnoughData):
2548 obj.decode(obj.encode()[:-1])
2550 @given(integers(min_value=1).map(tag_ctxc))
2551 def test_stripped_expl(self, tag_expl):
2552 obj = Null(expl=tag_expl)
2553 with self.assertRaises(NotEnoughData):
2554 obj.decode(obj.encode()[:-1])
2557 integers(min_value=31),
2558 integers(min_value=0),
2561 def test_bad_tag(self, tag, offset, decode_path):
2562 with self.assertRaises(DecodeError) as err:
2564 tag_encode(tag)[:-1],
2566 decode_path=decode_path,
2569 self.assertEqual(err.exception.offset, offset)
2570 self.assertEqual(err.exception.decode_path, decode_path)
2573 integers(min_value=128),
2574 integers(min_value=0),
2577 def test_bad_len(self, l, offset, decode_path):
2578 with self.assertRaises(DecodeError) as err:
2580 Null.tag_default + len_encode(l)[:-1],
2582 decode_path=decode_path,
2585 self.assertEqual(err.exception.offset, offset)
2586 self.assertEqual(err.exception.decode_path, decode_path)
2588 @given(binary(min_size=1))
2589 def test_tag_mismatch(self, impl):
2590 assume(impl != Null.tag_default)
2591 with self.assertRaises(TagMismatch):
2592 Null(impl=impl).decode(Null().encode())
2595 null_values_strategy(),
2596 integers(min_value=1).map(tag_ctxc),
2597 integers(min_value=0),
2601 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2602 for klass in (Null, NullInherited):
2603 _, _, optional, _decoded = values
2604 obj = klass(optional=optional, _decoded=_decoded)
2607 pprint(obj, big_blobs=True, with_decode_path=True)
2608 self.assertFalse(obj.expled)
2609 obj_encoded = obj.encode()
2610 self.assertEqual(encode2pass(obj), obj_encoded)
2611 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2612 obj_expled = obj(expl=tag_expl)
2613 self.assertTrue(obj_expled.expled)
2615 list(obj_expled.pps())
2616 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2617 obj_expled_encoded = obj_expled.encode()
2618 obj_expled_cer = encode_cer(obj_expled)
2619 self.assertNotEqual(obj_expled_cer, obj_encoded)
2620 self.assertSequenceEqual(
2621 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2624 ctx_copied = deepcopy(ctx_dummy)
2625 obj_decoded, tail = obj_expled.decode(
2626 obj_expled_encoded + tail_junk,
2630 self.assertDictEqual(ctx_copied, ctx_dummy)
2632 list(obj_decoded.pps())
2633 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2634 self.assertEqual(tail, tail_junk)
2635 self.assertEqual(obj_decoded, obj_expled)
2636 self.assertNotEqual(obj_decoded, obj)
2637 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2638 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2639 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2641 obj_decoded.expl_llen,
2642 len(len_encode(len(obj_encoded))),
2644 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2645 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2648 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2650 self.assertEqual(obj_decoded.expl_offset, offset)
2651 assert_exceeding_data(
2653 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2657 evgens = list(obj_expled.decode_evgen(
2658 obj_expled_encoded + tail_junk,
2660 decode_path=decode_path,
2663 self.assertEqual(len(evgens), 1)
2664 _decode_path, obj, tail = evgens[0]
2665 self.assertSequenceEqual(tail, tail_junk)
2666 self.assertEqual(_decode_path, decode_path)
2667 self.assertEqual(obj, obj_decoded)
2668 self.assertEqual(obj.expl_offset, offset)
2672 @given(integers(min_value=1))
2673 def test_invalid_len(self, l):
2674 with self.assertRaises(InvalidLength):
2675 Null().decode(b"".join((
2682 def oid_strategy(draw):
2683 first_arc = draw(integers(min_value=0, max_value=2))
2685 if first_arc in (0, 1):
2686 second_arc = draw(integers(min_value=0, max_value=39))
2688 second_arc = draw(integers(min_value=0))
2689 other_arcs = draw(lists(integers(min_value=0)))
2690 return tuple([first_arc, second_arc] + other_arcs)
2694 def oid_values_strategy(draw, do_expl=False):
2695 value = draw(one_of(none(), oid_strategy()))
2699 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2701 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2702 default = draw(one_of(none(), oid_strategy()))
2703 optional = draw(one_of(none(), booleans()))
2705 draw(integers(min_value=0)),
2706 draw(integers(min_value=0)),
2707 draw(integers(min_value=0)),
2709 return (value, impl, expl, default, optional, _decoded)
2712 class ObjectIdentifierInherited(ObjectIdentifier):
2716 class TestObjectIdentifier(CommonMixin, TestCase):
2717 base_klass = ObjectIdentifier
2719 def test_invalid_value_type(self):
2720 with self.assertRaises(InvalidValueType) as err:
2721 ObjectIdentifier(123)
2725 def test_optional(self, optional):
2726 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2727 self.assertTrue(obj.optional)
2729 @given(oid_strategy())
2730 def test_ready(self, value):
2731 obj = ObjectIdentifier()
2732 self.assertFalse(obj.ready)
2735 pprint(obj, big_blobs=True, with_decode_path=True)
2736 with self.assertRaises(ObjNotReady) as err:
2739 with self.assertRaises(ObjNotReady) as err:
2741 obj = ObjectIdentifier(value)
2742 self.assertTrue(obj.ready)
2743 self.assertFalse(obj.ber_encoded)
2746 pprint(obj, big_blobs=True, with_decode_path=True)
2749 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2750 def test_comparison(self, value1, value2, tag1, tag2):
2751 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2752 obj1 = klass(value1)
2753 obj2 = klass(value2)
2754 self.assertEqual(obj1 == obj2, value1 == value2)
2755 self.assertEqual(obj1 != obj2, value1 != value2)
2756 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2757 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2758 obj1 = klass(value1, impl=tag1)
2759 obj2 = klass(value1, impl=tag2)
2760 self.assertEqual(obj1 == obj2, tag1 == tag2)
2761 self.assertEqual(obj1 != obj2, tag1 != tag2)
2763 @given(lists(oid_strategy()))
2764 def test_sorted_works(self, values):
2765 self.assertSequenceEqual(
2766 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2770 @given(data_strategy())
2771 def test_call(self, d):
2772 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2780 ) = d.draw(oid_values_strategy())
2781 obj_initial = klass(
2782 value=value_initial,
2785 default=default_initial,
2786 optional=optional_initial or False,
2787 _decoded=_decoded_initial,
2796 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2805 value_expected = default if value is None else value
2807 default_initial if value_expected is None
2810 self.assertEqual(obj, value_expected)
2811 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2812 self.assertEqual(obj.expl_tag, expl or expl_initial)
2815 default_initial if default is None else default,
2817 if obj.default is None:
2818 optional = optional_initial if optional is None else optional
2819 optional = False if optional is None else optional
2822 self.assertEqual(obj.optional, optional)
2824 @given(oid_values_strategy())
2825 def test_copy(self, values):
2826 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2843 for copy_func in copy_funcs:
2844 obj_copied = copy_func(obj)
2845 self.assert_copied_basic_fields(obj, obj_copied)
2846 self.assertEqual(obj._value, obj_copied._value)
2848 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2851 integers(min_value=1).map(tag_encode),
2853 def test_stripped(self, value, tag_impl):
2854 obj = ObjectIdentifier(value, impl=tag_impl)
2855 with self.assertRaises(NotEnoughData):
2856 obj.decode(obj.encode()[:-1])
2860 integers(min_value=1).map(tag_ctxc),
2862 def test_stripped_expl(self, value, tag_expl):
2863 obj = ObjectIdentifier(value, expl=tag_expl)
2864 with self.assertRaises(NotEnoughData):
2865 obj.decode(obj.encode()[:-1])
2868 integers(min_value=31),
2869 integers(min_value=0),
2872 def test_bad_tag(self, tag, offset, decode_path):
2873 with self.assertRaises(DecodeError) as err:
2874 ObjectIdentifier().decode(
2875 tag_encode(tag)[:-1],
2877 decode_path=decode_path,
2880 self.assertEqual(err.exception.offset, offset)
2881 self.assertEqual(err.exception.decode_path, decode_path)
2884 integers(min_value=128),
2885 integers(min_value=0),
2888 def test_bad_len(self, l, offset, decode_path):
2889 with self.assertRaises(DecodeError) as err:
2890 ObjectIdentifier().decode(
2891 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2893 decode_path=decode_path,
2896 self.assertEqual(err.exception.offset, offset)
2897 self.assertEqual(err.exception.decode_path, decode_path)
2899 def test_zero_oid(self):
2900 with self.assertRaises(NotEnoughData):
2901 ObjectIdentifier().decode(
2902 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2905 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2906 @given(oid_strategy())
2907 def test_unfinished_oid(self, value):
2908 assume(list(value)[-1] > 255)
2909 obj_encoded = ObjectIdentifier(value).encode()
2910 obj, _ = ObjectIdentifier().decode(obj_encoded)
2911 data = obj_encoded[obj.tlen + obj.llen:-1]
2913 ObjectIdentifier.tag_default,
2914 len_encode(len(data)),
2917 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2920 @given(integers(min_value=0))
2921 def test_invalid_short(self, value):
2922 with self.assertRaises(InvalidOID):
2923 ObjectIdentifier((value,))
2924 with self.assertRaises(InvalidOID):
2925 ObjectIdentifier("%d" % value)
2927 @given(integers(min_value=3), integers(min_value=0))
2928 def test_invalid_first_arc(self, first_arc, second_arc):
2929 with self.assertRaises(InvalidOID):
2930 ObjectIdentifier((first_arc, second_arc))
2931 with self.assertRaises(InvalidOID):
2932 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2934 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2935 def test_invalid_second_arc(self, first_arc, second_arc):
2936 with self.assertRaises(InvalidOID):
2937 ObjectIdentifier((first_arc, second_arc))
2938 with self.assertRaises(InvalidOID):
2939 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2941 @given(text(alphabet=ascii_letters + ".", min_size=1))
2942 def test_junk(self, oid):
2943 with self.assertRaises(InvalidOID):
2944 ObjectIdentifier(oid)
2946 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2947 @given(oid_strategy())
2948 def test_validness(self, oid):
2949 obj = ObjectIdentifier(oid)
2950 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2953 pprint(obj, big_blobs=True, with_decode_path=True)
2955 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2957 oid_values_strategy(),
2959 integers(min_value=1).map(tag_ctxc),
2960 integers(min_value=0),
2964 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2965 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2966 _, _, _, default, optional, _decoded = values
2975 pprint(obj, big_blobs=True, with_decode_path=True)
2976 self.assertFalse(obj.expled)
2977 obj_encoded = obj.encode()
2978 self.assertEqual(encode2pass(obj), obj_encoded)
2979 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2980 obj_expled = obj(value, expl=tag_expl)
2981 self.assertTrue(obj_expled.expled)
2983 list(obj_expled.pps())
2984 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2985 obj_expled_encoded = obj_expled.encode()
2986 obj_expled_cer = encode_cer(obj_expled)
2987 self.assertNotEqual(obj_expled_cer, obj_encoded)
2988 self.assertSequenceEqual(
2989 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2992 ctx_copied = deepcopy(ctx_dummy)
2993 obj_decoded, tail = obj_expled.decode(
2994 obj_expled_encoded + tail_junk,
2998 self.assertDictEqual(ctx_copied, ctx_dummy)
3000 list(obj_decoded.pps())
3001 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3002 self.assertEqual(tail, tail_junk)
3003 self.assertEqual(obj_decoded, obj_expled)
3004 self.assertNotEqual(obj_decoded, obj)
3005 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
3006 self.assertEqual(tuple(obj_decoded), tuple(obj))
3007 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3008 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3009 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3011 obj_decoded.expl_llen,
3012 len(len_encode(len(obj_encoded))),
3014 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3015 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3018 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3020 self.assertEqual(obj_decoded.expl_offset, offset)
3021 assert_exceeding_data(
3023 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3027 evgens = list(obj_expled.decode_evgen(
3028 obj_expled_encoded + tail_junk,
3030 decode_path=decode_path,
3033 self.assertEqual(len(evgens), 1)
3034 _decode_path, obj, tail = evgens[0]
3035 self.assertSequenceEqual(tail, tail_junk)
3036 self.assertEqual(_decode_path, decode_path)
3037 self.assertEqual(obj, obj_decoded)
3038 self.assertEqual(obj.expl_offset, offset)
3043 oid_strategy().map(ObjectIdentifier),
3044 oid_strategy().map(ObjectIdentifier),
3046 def test_add(self, oid1, oid2):
3047 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3048 for oid_to_add in (oid2, tuple(oid2)):
3049 self.assertEqual(oid1 + oid_to_add, oid_expect)
3050 with self.assertRaises(InvalidValueType):
3053 def test_go_vectors_valid(self):
3054 for data, expect in (
3056 (b"\x55\x02", (2, 5, 2)),
3057 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3058 (b"\x81\x34\x03", (2, 100, 3)),
3061 ObjectIdentifier().decode(b"".join((
3062 ObjectIdentifier.tag_default,
3063 len_encode(len(data)),
3069 def test_go_vectors_invalid(self):
3070 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3071 with self.assertRaises(DecodeError):
3072 ObjectIdentifier().decode(b"".join((
3073 Integer.tag_default,
3074 len_encode(len(data)),
3078 def test_x690_vector(self):
3080 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3081 ObjectIdentifier((2, 999, 3)),
3084 def test_nonnormalized_first_arc(self):
3086 ObjectIdentifier.tag_default +
3089 ObjectIdentifier((1, 0)).encode()[-1:]
3091 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3092 self.assertTrue(obj.ber_encoded)
3093 self.assertTrue(obj.bered)
3095 self.assertTrue(obj.ber_encoded)
3096 self.assertTrue(obj.bered)
3097 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3098 ObjectIdentifier().decode(tampered)
3100 @given(data_strategy())
3101 def test_negative_arcs(self, d):
3102 oid = list(d.draw(oid_strategy()))
3105 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3107 if oid[idx - 1] == 0:
3109 with self.assertRaises(InvalidOID):
3110 ObjectIdentifier(tuple(oid))
3111 with self.assertRaises(InvalidOID):
3112 ObjectIdentifier(".".join(str(i) for i in oid))
3114 @given(data_strategy())
3115 def test_plused_arcs(self, d):
3116 oid = [str(arc) for arc in d.draw(oid_strategy())]
3117 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3118 oid[idx - 1] = "+" + oid[idx - 1]
3119 with self.assertRaises(InvalidOID):
3120 ObjectIdentifier(".".join(str(i) for i in oid))
3122 @given(data_strategy())
3123 def test_nonnormalized_arcs(self, d):
3124 arcs = d.draw(lists(
3125 integers(min_value=0, max_value=100),
3129 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3130 _, _, lv = tag_strip(dered)
3131 _, _, v = len_decode(lv)
3132 v_no_first_arc = v[1:]
3133 idx_for_tamper = d.draw(integers(
3135 max_value=len(v_no_first_arc) - 1,
3137 tampered = list(bytearray(v_no_first_arc))
3138 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3139 tampered.insert(idx_for_tamper, 0x80)
3140 tampered = bytes(bytearray(tampered))
3142 ObjectIdentifier.tag_default +
3143 len_encode(len(tampered)) +
3146 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3147 self.assertTrue(obj.ber_encoded)
3148 self.assertTrue(obj.bered)
3150 self.assertTrue(obj.ber_encoded)
3151 self.assertTrue(obj.bered)
3152 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3153 ObjectIdentifier().decode(tampered)
3157 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3159 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3160 values = list(draw(sets(
3162 min_size=len(schema),
3163 max_size=len(schema),
3165 schema = list(zip(schema, values))
3166 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3170 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3172 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3173 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3174 optional = draw(one_of(none(), booleans()))
3176 draw(integers(min_value=0)),
3177 draw(integers(min_value=0)),
3178 draw(integers(min_value=0)),
3180 return (schema, value, impl, expl, default, optional, _decoded)
3183 class TestEnumerated(CommonMixin, TestCase):
3184 class EWhatever(Enumerated):
3185 schema = (("whatever", 0),)
3187 base_klass = EWhatever
3189 def test_schema_required(self):
3190 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3193 def test_invalid_value_type(self):
3194 with self.assertRaises(InvalidValueType) as err:
3195 self.base_klass((1, 2))
3198 @given(sets(text_letters(), min_size=2))
3199 def test_unknown_name(self, schema_input):
3200 missing = schema_input.pop()
3202 class E(Enumerated):
3203 schema = [(n, 123) for n in schema_input]
3204 with self.assertRaises(ObjUnknown) as err:
3209 sets(text_letters(), min_size=2),
3210 sets(integers(), min_size=2),
3212 def test_unknown_value(self, schema_input, values_input):
3214 missing_value = values_input.pop()
3215 _input = list(zip(schema_input, values_input))
3217 class E(Enumerated):
3219 with self.assertRaises(DecodeError) as err:
3224 def test_optional(self, optional):
3225 obj = self.base_klass(default="whatever", optional=optional)
3226 self.assertTrue(obj.optional)
3228 def test_ready(self):
3229 obj = self.base_klass()
3230 self.assertFalse(obj.ready)
3233 pprint(obj, big_blobs=True, with_decode_path=True)
3234 with self.assertRaises(ObjNotReady) as err:
3237 obj = self.base_klass("whatever")
3238 self.assertTrue(obj.ready)
3241 pprint(obj, big_blobs=True, with_decode_path=True)
3243 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3244 def test_comparison(self, value1, value2, tag1, tag2):
3245 class E(Enumerated):
3247 ("whatever0", value1),
3248 ("whatever1", value2),
3251 class EInherited(E):
3253 for klass in (E, EInherited):
3254 obj1 = klass(value1)
3255 obj2 = klass(value2)
3256 self.assertEqual(obj1 == obj2, value1 == value2)
3257 self.assertEqual(obj1 != obj2, value1 != value2)
3258 self.assertEqual(obj1 == int(obj2), value1 == value2)
3259 obj1 = klass(value1, impl=tag1)
3260 obj2 = klass(value1, impl=tag2)
3261 self.assertEqual(obj1 == obj2, tag1 == tag2)
3262 self.assertEqual(obj1 != obj2, tag1 != tag2)
3264 @given(data_strategy())
3265 def test_call(self, d):
3274 ) = d.draw(enumerated_values_strategy())
3276 class E(Enumerated):
3277 schema = schema_initial
3279 value=value_initial,
3282 default=default_initial,
3283 optional=optional_initial or False,
3284 _decoded=_decoded_initial,
3294 ) = d.draw(enumerated_values_strategy(
3295 schema=schema_initial,
3296 do_expl=impl_initial is None,
3306 value_expected = default if value is None else value
3308 default_initial if value_expected is None
3313 dict(schema_initial).get(value_expected, value_expected),
3315 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3316 self.assertEqual(obj.expl_tag, expl or expl_initial)
3319 default_initial if default is None else default,
3321 if obj.default is None:
3322 optional = optional_initial if optional is None else optional
3323 optional = False if optional is None else optional
3326 self.assertEqual(obj.optional, optional)
3327 self.assertEqual(obj.specs, dict(schema_initial))
3329 @given(enumerated_values_strategy())
3330 def test_copy(self, values):
3331 schema_input, value, impl, expl, default, optional, _decoded = values
3333 class E(Enumerated):
3334 schema = schema_input
3344 for copy_func in copy_funcs:
3345 obj_copied = copy_func(obj)
3346 self.assert_copied_basic_fields(obj, obj_copied)
3347 self.assertEqual(obj.specs, obj_copied.specs)
3349 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3350 @given(data_strategy())
3351 def test_symmetric(self, d):
3352 schema_input, _, _, _, default, optional, _decoded = d.draw(
3353 enumerated_values_strategy(),
3355 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3356 offset = d.draw(integers(min_value=0))
3357 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3358 tail_junk = d.draw(binary(max_size=5))
3359 decode_path = d.draw(decode_path_strat)
3361 class E(Enumerated):
3362 schema = schema_input
3371 pprint(obj, big_blobs=True, with_decode_path=True)
3372 self.assertFalse(obj.expled)
3373 obj_encoded = obj.encode()
3374 self.assertEqual(encode2pass(obj), obj_encoded)
3375 obj_expled = obj(value, expl=tag_expl)
3376 self.assertTrue(obj_expled.expled)
3378 list(obj_expled.pps())
3379 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3380 obj_expled_encoded = obj_expled.encode()
3381 ctx_copied = deepcopy(ctx_dummy)
3382 obj_decoded, tail = obj_expled.decode(
3383 obj_expled_encoded + tail_junk,
3387 self.assertDictEqual(ctx_copied, ctx_dummy)
3389 list(obj_decoded.pps())
3390 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3391 self.assertEqual(tail, tail_junk)
3392 self.assertEqual(obj_decoded, obj_expled)
3393 self.assertNotEqual(obj_decoded, obj)
3394 self.assertEqual(int(obj_decoded), int(obj_expled))
3395 self.assertEqual(int(obj_decoded), int(obj))
3396 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3397 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3398 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3400 obj_decoded.expl_llen,
3401 len(len_encode(len(obj_encoded))),
3403 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3404 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3407 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3409 self.assertEqual(obj_decoded.expl_offset, offset)
3410 assert_exceeding_data(
3412 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3416 evgens = list(obj_expled.decode_evgen(
3417 obj_expled_encoded + tail_junk,
3419 decode_path=decode_path,
3422 self.assertEqual(len(evgens), 1)
3423 _decode_path, obj, tail = evgens[0]
3424 self.assertSequenceEqual(tail, tail_junk)
3425 self.assertEqual(_decode_path, decode_path)
3426 self.assertEqual(obj, obj_decoded)
3427 self.assertEqual(obj.expl_offset, offset)
3433 def string_values_strategy(draw, alphabet, do_expl=False):
3434 bound_min, bound_max = sorted(draw(sets(
3435 integers(min_value=0, max_value=1 << 7),
3439 value = draw(one_of(
3441 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3443 default = draw(one_of(
3445 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3448 if draw(booleans()):
3449 bounds = (bound_min, bound_max)
3453 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3455 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3456 optional = draw(one_of(none(), booleans()))
3458 draw(integers(min_value=0)),
3459 draw(integers(min_value=0)),
3460 draw(integers(min_value=0)),
3462 return (value, bounds, impl, expl, default, optional, _decoded)
3465 class StringMixin(object):
3466 def test_invalid_value_type(self):
3467 with self.assertRaises(InvalidValueType) as err:
3468 self.base_klass((1, 2))
3471 def text_alphabet(self):
3472 return "".join(six_unichr(c) for c in six_xrange(256))
3475 def test_optional(self, optional):
3476 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3477 self.assertTrue(obj.optional)
3479 @given(data_strategy())
3480 def test_ready(self, d):
3481 obj = self.base_klass()
3482 self.assertFalse(obj.ready)
3485 pprint(obj, big_blobs=True, with_decode_path=True)
3487 with self.assertRaises(ObjNotReady) as err:
3490 with self.assertRaises(ObjNotReady) as err:
3492 value = d.draw(text(alphabet=self.text_alphabet()))
3493 obj = self.base_klass(value)
3494 self.assertTrue(obj.ready)
3497 pprint(obj, big_blobs=True, with_decode_path=True)
3500 @given(data_strategy())
3501 def test_comparison(self, d):
3502 value1 = d.draw(text(alphabet=self.text_alphabet()))
3503 value2 = d.draw(text(alphabet=self.text_alphabet()))
3504 tag1 = d.draw(binary(min_size=1))
3505 tag2 = d.draw(binary(min_size=1))
3506 obj1 = self.base_klass(value1)
3507 obj2 = self.base_klass(value2)
3508 self.assertEqual(obj1 == obj2, value1 == value2)
3509 self.assertEqual(obj1 != obj2, value1 != value2)
3510 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3511 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3512 obj1 = self.base_klass(value1, impl=tag1)
3513 obj2 = self.base_klass(value1, impl=tag2)
3514 self.assertEqual(obj1 == obj2, tag1 == tag2)
3515 self.assertEqual(obj1 != obj2, tag1 != tag2)
3517 @given(data_strategy())
3518 def test_bounds_satisfied(self, d):
3519 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3520 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3521 value = d.draw(text(
3522 alphabet=self.text_alphabet(),
3526 self.base_klass(value=value, bounds=(bound_min, bound_max))
3528 @given(data_strategy())
3529 def test_bounds_unsatisfied(self, d):
3530 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3531 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3532 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3533 with self.assertRaises(BoundsError) as err:
3534 self.base_klass(value=value, bounds=(bound_min, bound_max))
3536 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3537 self.base_klass(bounds=(bound_min, bound_max)).decode(
3538 self.base_klass(value).encode()
3541 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3542 self.base_klass(bounds=(bound_min, bound_max)).decode(
3543 encode2pass(self.base_klass(value))
3545 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3546 with self.assertRaises(BoundsError) as err:
3547 self.base_klass(value=value, bounds=(bound_min, bound_max))
3549 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3550 self.base_klass(bounds=(bound_min, bound_max)).decode(
3551 self.base_klass(value).encode()
3554 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3555 self.base_klass(bounds=(bound_min, bound_max)).decode(
3556 encode2pass(self.base_klass(value))
3559 @given(data_strategy())
3560 def test_call(self, d):
3569 ) = d.draw(string_values_strategy(self.text_alphabet()))
3570 obj_initial = self.base_klass(
3576 optional_initial or False,
3587 ) = d.draw(string_values_strategy(
3588 self.text_alphabet(),
3589 do_expl=impl_initial is None,
3591 if (default is None) and (obj_initial.default is not None):
3594 (bounds is None) and
3595 (value is not None) and
3596 (bounds_initial is not None) and
3597 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3601 (bounds is None) and
3602 (default is not None) and
3603 (bounds_initial is not None) and
3604 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3607 obj = obj_initial(value, bounds, impl, expl, default, optional)
3609 value_expected = default if value is None else value
3611 default_initial if value_expected is None
3614 self.assertEqual(obj, value_expected)
3615 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3616 self.assertEqual(obj.expl_tag, expl or expl_initial)
3619 default_initial if default is None else default,
3621 if obj.default is None:
3622 optional = optional_initial if optional is None else optional
3623 optional = False if optional is None else optional
3626 self.assertEqual(obj.optional, optional)
3628 (obj._bound_min, obj._bound_max),
3629 bounds or bounds_initial or (0, float("+inf")),
3632 @given(data_strategy())
3633 def test_copy(self, d):
3634 values = d.draw(string_values_strategy(self.text_alphabet()))
3635 obj = self.base_klass(*values)
3636 for copy_func in copy_funcs:
3637 obj_copied = copy_func(obj)
3638 self.assert_copied_basic_fields(obj, obj_copied)
3639 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3640 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3641 self.assertEqual(obj._value, obj_copied._value)
3643 @given(data_strategy())
3644 def test_stripped(self, d):
3645 value = d.draw(text(alphabet=self.text_alphabet()))
3646 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3647 obj = self.base_klass(value, impl=tag_impl)
3648 with self.assertRaises(NotEnoughData):
3649 obj.decode(obj.encode()[:-1])
3651 @given(data_strategy())
3652 def test_stripped_expl(self, d):
3653 value = d.draw(text(alphabet=self.text_alphabet()))
3654 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3655 obj = self.base_klass(value, expl=tag_expl)
3656 with self.assertRaises(NotEnoughData):
3657 obj.decode(obj.encode()[:-1])
3660 integers(min_value=31),
3661 integers(min_value=0),
3664 def test_bad_tag(self, tag, offset, decode_path):
3665 with self.assertRaises(DecodeError) as err:
3666 self.base_klass().decode(
3667 tag_encode(tag)[:-1],
3669 decode_path=decode_path,
3672 self.assertEqual(err.exception.offset, offset)
3673 self.assertEqual(err.exception.decode_path, decode_path)
3676 integers(min_value=128),
3677 integers(min_value=0),
3680 def test_bad_len(self, l, offset, decode_path):
3681 with self.assertRaises(DecodeError) as err:
3682 self.base_klass().decode(
3683 self.base_klass.tag_default + len_encode(l)[:-1],
3685 decode_path=decode_path,
3688 self.assertEqual(err.exception.offset, offset)
3689 self.assertEqual(err.exception.decode_path, decode_path)
3692 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3693 integers(min_value=0),
3696 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3697 value, bound_min = list(sorted(ints))
3699 class String(self.base_klass):
3700 # Multiply this value by four, to satisfy UTF-32 bounds
3701 # (4 bytes per character) validation
3702 bounds = (bound_min * 4, bound_min * 4)
3703 with self.assertRaises(DecodeError) as err:
3705 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3707 decode_path=decode_path,
3710 self.assertEqual(err.exception.offset, offset)
3711 self.assertEqual(err.exception.decode_path, decode_path)
3713 @given(data_strategy())
3714 def test_symmetric(self, d):
3715 values = d.draw(string_values_strategy(self.text_alphabet()))
3716 value = d.draw(text(alphabet=self.text_alphabet()))
3717 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3718 offset = d.draw(integers(min_value=0))
3719 tail_junk = d.draw(binary(max_size=5))
3720 decode_path = d.draw(decode_path_strat)
3721 _, _, _, _, default, optional, _decoded = values
3722 obj = self.base_klass(
3730 pprint(obj, big_blobs=True, with_decode_path=True)
3731 self.assertFalse(obj.expled)
3732 obj_encoded = obj.encode()
3733 self.assertEqual(encode2pass(obj), obj_encoded)
3734 obj_expled = obj(value, expl=tag_expl)
3735 self.assertTrue(obj_expled.expled)
3737 list(obj_expled.pps())
3738 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3739 obj_expled_encoded = obj_expled.encode()
3740 ctx_copied = deepcopy(ctx_dummy)
3741 obj_decoded, tail = obj_expled.decode(
3742 obj_expled_encoded + tail_junk,
3746 self.assertDictEqual(ctx_copied, ctx_dummy)
3748 list(obj_decoded.pps())
3749 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3750 self.assertEqual(tail, tail_junk)
3751 self.assertEqual(obj_decoded, obj_expled)
3752 self.assertNotEqual(obj_decoded, obj)
3753 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3754 self.assertEqual(bytes(obj_decoded), bytes(obj))
3755 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3756 self.assertEqual(text_type(obj_decoded), text_type(obj))
3757 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3758 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3759 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3761 obj_decoded.expl_llen,
3762 len(len_encode(len(obj_encoded))),
3764 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3765 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3768 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3770 self.assertEqual(obj_decoded.expl_offset, offset)
3771 assert_exceeding_data(
3773 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3777 evgens = list(obj_expled.decode_evgen(
3778 obj_expled_encoded + tail_junk,
3780 decode_path=decode_path,
3783 self.assertEqual(len(evgens), 1)
3784 _decode_path, obj, tail = evgens[0]
3785 self.assertSequenceEqual(tail, tail_junk)
3786 self.assertEqual(_decode_path, decode_path)
3787 if not getattr(self, "evgen_mode_skip_value", True):
3788 self.assertEqual(obj, obj_decoded)
3789 self.assertEqual(obj.expl_offset, offset)
3794 cyrillic_letters = text(
3795 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3801 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3802 base_klass = UTF8String
3804 @given(cyrillic_letters)
3805 def test_byte_per_primitive(self, chars):
3807 char_raw = char.encode("utf-8")
3808 encoded = b"".join((
3809 self.base_klass().tag_constructed,
3811 OctetString(char_raw[:1]).encode(),
3812 OctetString(char_raw[1:2]).encode(),
3816 self.base_klass().decod(encoded, ctx={"bered": True}),
3821 class UnicodeDecodeErrorMixin(object):
3822 @given(cyrillic_letters)
3823 def test_unicode_decode_error(self, cyrillic_text):
3824 with self.assertRaises(DecodeError):
3825 self.base_klass(cyrillic_text)
3828 class TestNumericString(StringMixin, CommonMixin, TestCase):
3829 base_klass = NumericString
3831 def text_alphabet(self):
3834 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3835 def test_non_numeric(self, non_numeric_text):
3836 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3837 self.base_klass(non_numeric_text)
3840 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3841 integers(min_value=0),
3844 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3845 value, bound_min = list(sorted(ints))
3847 class String(self.base_klass):
3848 bounds = (bound_min, bound_min)
3849 with self.assertRaises(DecodeError) as err:
3851 self.base_klass(b"1" * value).encode(),
3853 decode_path=decode_path,
3856 self.assertEqual(err.exception.offset, offset)
3857 self.assertEqual(err.exception.decode_path, decode_path)
3859 def test_byte_per_primitive(self):
3860 encoded = b"".join((
3861 self.base_klass().tag_constructed,
3863 OctetString(b"1").encode(),
3864 OctetString(b"2").encode(),
3868 self.base_klass().decod(encoded, ctx={"bered": True}),
3873 class TestPrintableString(
3874 UnicodeDecodeErrorMixin,
3879 base_klass = PrintableString
3881 def text_alphabet(self):
3882 return ascii_letters + digits + " '()+,-./:=?"
3884 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3885 def test_non_printable(self, non_printable_text):
3886 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3887 self.base_klass(non_printable_text)
3890 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3891 integers(min_value=0),
3894 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3895 value, bound_min = list(sorted(ints))
3897 class String(self.base_klass):
3898 bounds = (bound_min, bound_min)
3899 with self.assertRaises(DecodeError) as err:
3901 self.base_klass(b"1" * value).encode(),
3903 decode_path=decode_path,
3906 self.assertEqual(err.exception.offset, offset)
3907 self.assertEqual(err.exception.decode_path, decode_path)
3909 def test_allowable_invalid_chars(self):
3911 ("*", {"allow_asterisk": True}),
3912 ("&", {"allow_ampersand": True}),
3913 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3916 obj = self.base_klass(s)
3917 for prop in kwargs.keys():
3918 self.assertFalse(getattr(obj, prop))
3920 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3922 self.base_klass(s, **kwargs)
3923 klass = self.base_klass(**kwargs)
3925 for prop in kwargs.keys():
3926 self.assertTrue(getattr(obj, prop))
3929 for prop in kwargs.keys():
3930 self.assertTrue(getattr(obj, prop))
3933 class TestTeletexString(
3934 UnicodeDecodeErrorMixin,
3939 base_klass = TeletexString
3942 class TestVideotexString(
3943 UnicodeDecodeErrorMixin,
3948 base_klass = VideotexString
3951 class TestIA5String(
3952 UnicodeDecodeErrorMixin,
3957 base_klass = IA5String
3959 def text_alphabet(self):
3960 return "".join(six_unichr(c) for c in six_xrange(128))
3962 @given(integers(min_value=128, max_value=255))
3963 def test_alphabet_bad(self, code):
3964 with self.assertRaises(DecodeError):
3965 self.base_klass().decod(
3966 self.base_klass.tag_default +
3968 bytes(bytearray([code])),
3972 class TestGraphicString(
3973 UnicodeDecodeErrorMixin,
3978 base_klass = GraphicString
3981 class TestVisibleString(
3982 UnicodeDecodeErrorMixin,
3987 base_klass = VisibleString
3989 def text_alphabet(self):
3990 return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
3992 def test_x690_vector(self):
3993 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3994 self.assertSequenceEqual(tail, b"")
3995 self.assertEqual(str(obj), "Jones")
3996 self.assertFalse(obj.ber_encoded)
3997 self.assertFalse(obj.lenindef)
3998 self.assertFalse(obj.bered)
4000 obj, tail = VisibleString().decode(
4001 hexdec("3A0904034A6F6E04026573"),
4002 ctx={"bered": True},
4004 self.assertSequenceEqual(tail, b"")
4005 self.assertEqual(str(obj), "Jones")
4006 self.assertTrue(obj.ber_encoded)
4007 self.assertFalse(obj.lenindef)
4008 self.assertTrue(obj.bered)
4010 self.assertTrue(obj.ber_encoded)
4011 self.assertFalse(obj.lenindef)
4012 self.assertTrue(obj.bered)
4014 obj, tail = VisibleString().decode(
4015 hexdec("3A8004034A6F6E040265730000"),
4016 ctx={"bered": True},
4018 self.assertSequenceEqual(tail, b"")
4019 self.assertEqual(str(obj), "Jones")
4020 self.assertTrue(obj.ber_encoded)
4021 self.assertTrue(obj.lenindef)
4022 self.assertTrue(obj.bered)
4024 self.assertTrue(obj.ber_encoded)
4025 self.assertTrue(obj.lenindef)
4026 self.assertTrue(obj.bered)
4029 integers(min_value=0, max_value=ord(" ") - 1),
4030 integers(min_value=ord("~") + 1, max_value=255),
4032 def test_alphabet_bad(self, code):
4033 with self.assertRaises(DecodeError):
4034 self.base_klass().decod(
4035 self.base_klass.tag_default +
4037 bytes(bytearray([code])),
4041 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
4042 integers(min_value=0),
4045 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
4046 value, bound_min = list(sorted(ints))
4048 class String(self.base_klass):
4049 bounds = (bound_min, bound_min)
4050 with self.assertRaises(DecodeError) as err:
4052 self.base_klass(b"1" * value).encode(),
4054 decode_path=decode_path,
4057 self.assertEqual(err.exception.offset, offset)
4058 self.assertEqual(err.exception.decode_path, decode_path)
4061 class TestGeneralString(
4062 UnicodeDecodeErrorMixin,
4067 base_klass = GeneralString
4070 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4071 base_klass = UniversalString
4074 class TestBMPString(StringMixin, CommonMixin, TestCase):
4075 base_klass = BMPString
4079 def generalized_time_values_strategy(
4087 if draw(booleans()):
4088 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4090 value = value.replace(microsecond=0)
4092 if draw(booleans()):
4093 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4095 default = default.replace(microsecond=0)
4099 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4101 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4102 optional = draw(one_of(none(), booleans()))
4104 draw(integers(min_value=0)),
4105 draw(integers(min_value=0)),
4106 draw(integers(min_value=0)),
4108 return (value, impl, expl, default, optional, _decoded)
4111 class TimeMixin(object):
4112 def test_invalid_value_type(self):
4113 with self.assertRaises(InvalidValueType) as err:
4114 self.base_klass(datetime.now().timetuple())
4117 @given(data_strategy())
4118 def test_optional(self, d):
4119 default = d.draw(datetimes(
4120 min_value=self.min_datetime,
4121 max_value=self.max_datetime,
4123 optional = d.draw(booleans())
4124 obj = self.base_klass(default=default, optional=optional)
4125 self.assertTrue(obj.optional)
4127 @given(data_strategy())
4128 def test_ready(self, d):
4129 obj = self.base_klass()
4130 self.assertFalse(obj.ready)
4133 pprint(obj, big_blobs=True, with_decode_path=True)
4134 with self.assertRaises(ObjNotReady) as err:
4137 with self.assertRaises(ObjNotReady) as err:
4139 value = d.draw(datetimes(
4140 min_value=self.min_datetime,
4141 max_value=self.max_datetime,
4143 obj = self.base_klass(value)
4144 self.assertTrue(obj.ready)
4147 pprint(obj, big_blobs=True, with_decode_path=True)
4149 @given(data_strategy())
4150 def test_comparison(self, d):
4151 value1 = d.draw(datetimes(
4152 min_value=self.min_datetime,
4153 max_value=self.max_datetime,
4155 value2 = d.draw(datetimes(
4156 min_value=self.min_datetime,
4157 max_value=self.max_datetime,
4159 tag1 = d.draw(binary(min_size=1))
4160 tag2 = d.draw(binary(min_size=1))
4162 value1 = value1.replace(microsecond=0)
4163 value2 = value2.replace(microsecond=0)
4164 obj1 = self.base_klass(value1)
4165 obj2 = self.base_klass(value2)
4166 self.assertEqual(obj1 == obj2, value1 == value2)
4167 self.assertEqual(obj1 != obj2, value1 != value2)
4168 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4169 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4170 obj1 = self.base_klass(value1, impl=tag1)
4171 obj2 = self.base_klass(value1, impl=tag2)
4172 self.assertEqual(obj1 == obj2, tag1 == tag2)
4173 self.assertEqual(obj1 != obj2, tag1 != tag2)
4175 @given(data_strategy())
4176 def test_call(self, d):
4184 ) = d.draw(generalized_time_values_strategy(
4185 min_datetime=self.min_datetime,
4186 max_datetime=self.max_datetime,
4187 omit_ms=self.omit_ms,
4189 obj_initial = self.base_klass(
4190 value=value_initial,
4193 default=default_initial,
4194 optional=optional_initial or False,
4195 _decoded=_decoded_initial,
4204 ) = d.draw(generalized_time_values_strategy(
4205 min_datetime=self.min_datetime,
4206 max_datetime=self.max_datetime,
4207 omit_ms=self.omit_ms,
4208 do_expl=impl_initial is None,
4218 value_expected = default if value is None else value
4220 default_initial if value_expected is None
4223 self.assertEqual(obj, value_expected)
4224 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4225 self.assertEqual(obj.expl_tag, expl or expl_initial)
4228 default_initial if default is None else default,
4230 if obj.default is None:
4231 optional = optional_initial if optional is None else optional
4232 optional = False if optional is None else optional
4235 self.assertEqual(obj.optional, optional)
4237 @given(data_strategy())
4238 def test_copy(self, d):
4239 values = d.draw(generalized_time_values_strategy(
4240 min_datetime=self.min_datetime,
4241 max_datetime=self.max_datetime,
4243 obj = self.base_klass(*values)
4244 for copy_func in copy_funcs:
4245 obj_copied = copy_func(obj)
4246 self.assert_copied_basic_fields(obj, obj_copied)
4247 self.assertEqual(obj._value, obj_copied._value)
4249 @given(data_strategy())
4250 def test_stripped(self, d):
4251 value = d.draw(datetimes(
4252 min_value=self.min_datetime,
4253 max_value=self.max_datetime,
4255 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4256 obj = self.base_klass(value, impl=tag_impl)
4257 with self.assertRaises(NotEnoughData):
4258 obj.decode(obj.encode()[:-1])
4260 @given(data_strategy())
4261 def test_stripped_expl(self, d):
4262 value = d.draw(datetimes(
4263 min_value=self.min_datetime,
4264 max_value=self.max_datetime,
4266 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4267 obj = self.base_klass(value, expl=tag_expl)
4268 with self.assertRaises(NotEnoughData):
4269 obj.decode(obj.encode()[:-1])
4271 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4272 @given(data_strategy())
4273 def test_symmetric(self, d):
4274 values = d.draw(generalized_time_values_strategy(
4275 min_datetime=self.min_datetime,
4276 max_datetime=self.max_datetime,
4278 value = d.draw(datetimes(
4279 min_value=self.min_datetime,
4280 max_value=self.max_datetime,
4282 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4283 offset = d.draw(integers(min_value=0))
4284 tail_junk = d.draw(binary(max_size=5))
4285 _, _, _, default, optional, _decoded = values
4286 obj = self.base_klass(
4294 pprint(obj, big_blobs=True, with_decode_path=True)
4295 self.assertFalse(obj.expled)
4296 obj_encoded = obj.encode()
4297 self.assertEqual(encode2pass(obj), obj_encoded)
4298 self.additional_symmetric_check(value, obj_encoded)
4299 obj_expled = obj(value, expl=tag_expl)
4300 self.assertTrue(obj_expled.expled)
4302 list(obj_expled.pps())
4303 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4304 obj_expled_encoded = obj_expled.encode()
4305 ctx_copied = deepcopy(ctx_dummy)
4306 obj_decoded, tail = obj_expled.decode(
4307 obj_expled_encoded + tail_junk,
4311 self.assertDictEqual(ctx_copied, ctx_dummy)
4313 list(obj_decoded.pps())
4314 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4315 self.assertEqual(tail, tail_junk)
4316 self.assertEqual(obj_decoded, obj_expled)
4317 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4318 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4319 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4320 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4321 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4323 obj_decoded.expl_llen,
4324 len(len_encode(len(obj_encoded))),
4326 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4327 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4330 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4332 self.assertEqual(obj_decoded.expl_offset, offset)
4333 assert_exceeding_data(
4335 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4340 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4341 base_klass = GeneralizedTime
4343 min_datetime = datetime(1900, 1, 1)
4344 max_datetime = datetime(9999, 12, 31)
4345 evgen_mode_skip_value = False
4347 def additional_symmetric_check(self, value, obj_encoded):
4348 if value.microsecond > 0:
4349 self.assertFalse(obj_encoded.endswith(b"0Z"))
4351 def test_repr_not_ready(self):
4352 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4353 repr(GeneralizedTime())
4355 def test_x690_vector_valid(self):
4359 b"19920722132100.3Z",
4361 GeneralizedTime(data)
4363 def test_x690_vector_invalid(self):
4366 b"19920622123421.0Z",
4367 b"19920722132100.30Z",
4369 with self.assertRaises(DecodeError) as err:
4370 GeneralizedTime(data)
4373 def test_go_vectors_invalid(self):
4385 b"-20100102030410Z",
4386 b"2010-0102030410Z",
4387 b"2010-0002030410Z",
4388 b"201001-02030410Z",
4389 b"20100102-030410Z",
4390 b"2010010203-0410Z",
4391 b"201001020304-10Z",
4392 # These ones are INVALID in *DER*, but accepted
4393 # by Go's encoding/asn1
4394 b"20100102030405+0607",
4395 b"20100102030405-0607",
4397 with self.assertRaises(DecodeError) as err:
4398 GeneralizedTime(data)
4401 def test_go_vectors_valid(self):
4403 GeneralizedTime(b"20100102030405Z").todatetime(),
4404 datetime(2010, 1, 2, 3, 4, 5, 0),
4407 def test_go_vectors_valid_ber(self):
4409 b"20100102030405+0607",
4410 b"20100102030405-0607",
4412 GeneralizedTime(data, ctx={"bered": True})
4414 def test_utc_offsets(self):
4415 """Some know equal UTC offsets
4418 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4422 "200101011130-0700",
4423 "200101011500-03:30",
4426 self.assertEqual(dts[0], dts[1])
4427 self.assertEqual(dts[0], dts[2])
4428 self.assertEqual(dts[0], dts[3])
4430 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4431 @given(data_strategy())
4432 def test_valid_ber(self, d):
4433 min_year = 1901 if PY2 else 2
4434 year = d.draw(integers(min_value=min_year, max_value=9999))
4435 month = d.draw(integers(min_value=1, max_value=12))
4436 day = d.draw(integers(min_value=1, max_value=28))
4437 hours = d.draw(integers(min_value=0, max_value=23))
4438 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4439 dt = datetime(year, month, day, hours)
4440 fractions_sign = d.draw(sampled_from(" ,."))
4442 if fractions_sign != " ":
4443 fractions = random()
4444 if d.draw(booleans()):
4445 minutes = d.draw(integers(min_value=0, max_value=59))
4446 data += "%02d" % minutes
4447 dt += timedelta(seconds=60 * minutes)
4448 if d.draw(booleans()):
4449 seconds = d.draw(integers(min_value=0, max_value=59))
4450 data += "%02d" % seconds
4451 dt += timedelta(seconds=seconds)
4452 if fractions is not None:
4453 dt += timedelta(microseconds=10**6 * fractions)
4454 elif fractions is not None:
4455 dt += timedelta(seconds=60 * fractions)
4456 elif fractions is not None:
4457 dt += timedelta(seconds=3600 * fractions)
4458 if fractions is not None:
4459 data += fractions_sign + str(fractions)[2:]
4460 if d.draw(booleans()):
4462 elif d.draw(booleans()):
4463 offset_hour = d.draw(integers(min_value=0, max_value=13))
4465 if d.draw(booleans()):
4470 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4471 data += "%02d" % offset_hour
4472 minutes_separator = d.draw(sampled_from((None, "", ":")))
4473 if minutes_separator is not None:
4474 offset_minute = d.draw(integers(min_value=0, max_value=59))
4475 dt -= timedelta(seconds=sign * 60 * offset_minute)
4476 data += "%s%02d" % (minutes_separator, offset_minute)
4477 data = data.encode("ascii")
4478 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4480 GeneralizedTime().decod(data_der)
4485 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4488 mktime(obj.todatetime().timetuple()),
4489 mktime(dt.timetuple()),
4492 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4493 self.assertEqual(obj.ber_encoded, not dered)
4494 self.assertEqual(obj.bered, not dered)
4495 self.assertEqual(obj.ber_raw, None if dered else data)
4496 self.assertEqual(obj.encode() == data_der, dered)
4501 def test_invalid_ber(self):
4503 # "00010203040506.07",
4504 "-0010203040506.07",
4505 "0001-203040506.07",
4506 "000102-3040506.07",
4507 "00010203-40506.07",
4508 "0001020304-506.07",
4509 "000102030405-6.07",
4510 "00010203040506.-7",
4511 "+0010203040506.07",
4512 "0001+203040506.07",
4513 "000102+3040506.07",
4514 "00010203+40506.07",
4515 "0001020304+506.07",
4516 "000102030405+6.07",
4517 "00010203040506.+7",
4518 " 0010203040506.07",
4519 "0001 203040506.07",
4520 "000102 3040506.07",
4521 "00010203 40506.07",
4522 "0001020304 506.07",
4523 "000102030405 6.07",
4524 "00010203040506. 7",
4525 "001 0203040506.07",
4526 "00012 03040506.07",
4527 "0001023 040506.07",
4528 "000102034 0506.07",
4529 "00010203045 06.07",
4530 "0001020304056 .07",
4531 "00010203040506.7 ",
4611 "00010203040506.07+15",
4612 "00010203040506.07-15",
4613 "00010203040506.07+14:60",
4614 "00010203040506.07+1460",
4615 "00010203040506.07-1460",
4616 "00010203040506.07+00:60",
4617 "00010203040506.07-00:60",
4619 "00010203040506+15",
4620 "00010203040506-15",
4621 "00010203040506+14:60",
4622 "00010203040506+1460",
4623 "00010203040506-1460",
4624 "00010203040506+00:60",
4625 "00010203040506-00:60",
4634 with self.assertRaises(DecodeError):
4635 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4636 data = data.replace(".", ",")
4637 with self.assertRaises(DecodeError):
4638 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4642 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4643 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4645 binary(min_size=1, max_size=1),
4647 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4648 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4651 def test_junk(self, part0, part1, part2):
4652 junk = part0 + part1 + part2
4653 assume(not (set(junk) <= set(digits.encode("ascii"))))
4654 with self.assertRaises(DecodeError):
4655 GeneralizedTime().decode(
4656 GeneralizedTime.tag_default +
4657 len_encode(len(junk)) +
4663 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4664 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4666 binary(min_size=1, max_size=1),
4668 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4669 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4672 def test_junk_dm(self, part0, part1, part2):
4673 junk = part0 + part1 + part2
4674 assume(not (set(junk) <= set(digits.encode("ascii"))))
4675 with self.assertRaises(DecodeError):
4676 GeneralizedTime().decode(
4677 GeneralizedTime.tag_default +
4678 len_encode(len(junk)) +
4682 def test_ns_fractions(self):
4683 GeneralizedTime(b"20010101000000.000001Z")
4684 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4685 GeneralizedTime(b"20010101000000.0000001Z")
4687 def test_non_pure_integers(self):
4689 # b"20000102030405Z,
4696 b"20000102030405.+6Z",
4697 b"20000102030405.-6Z",
4704 b"20000102030405._6Z",
4705 b"20000102030405.6_Z",
4712 b"20000102030405. 6Z",
4719 b"20000102030405.6 Z",
4721 with self.assertRaises(DecodeError):
4722 GeneralizedTime(data)
4725 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4726 base_klass = UTCTime
4728 min_datetime = datetime(2000, 1, 1)
4729 max_datetime = datetime(2049, 12, 31)
4730 evgen_mode_skip_value = False
4732 def additional_symmetric_check(self, value, obj_encoded):
4735 def test_repr_not_ready(self):
4736 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4739 def test_x690_vector_valid(self):
4747 def test_x690_vector_invalid(self):
4752 with self.assertRaises(DecodeError) as err:
4756 def test_go_vectors_invalid(self):
4782 # These ones are INVALID in *DER*, but accepted
4783 # by Go's encoding/asn1
4784 b"910506164540-0700",
4785 b"910506164540+0730",
4789 with self.assertRaises(DecodeError) as err:
4793 def test_go_vectors_valid(self):
4795 UTCTime(b"910506234540Z").todatetime(),
4796 datetime(1991, 5, 6, 23, 45, 40, 0),
4799 def test_non_pure_integers(self):
4828 with self.assertRaises(DecodeError):
4831 def test_x680_vector_valid_ber(self):
4833 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4834 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4835 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4836 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4838 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4839 obj = UTCTime().decod(data_der, ctx={"bered": True})
4840 self.assertEqual(obj, dt)
4841 self.assertEqual(obj.todatetime(), dt)
4842 self.assertTrue(obj.ber_encoded)
4843 self.assertTrue(obj.bered)
4844 self.assertEqual(obj.ber_raw, data)
4845 self.assertNotEqual(obj.encode(), data_der)
4848 def test_go_vectors_valid_ber(self):
4850 b"910506164540-0700",
4851 b"910506164540+0730",
4855 data = UTCTime.tag_default + len_encode(len(data)) + data
4856 obj = UTCTime().decod(data, ctx={"bered": True})
4857 self.assertTrue(obj.ber_encoded)
4858 self.assertTrue(obj.bered)
4859 self.assertNotEqual(obj.encode(), data)
4862 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4863 @given(data_strategy())
4864 def test_valid_ber(self, d):
4865 year = d.draw(integers(min_value=0, max_value=99))
4866 month = d.draw(integers(min_value=1, max_value=12))
4867 day = d.draw(integers(min_value=1, max_value=28))
4868 hours = d.draw(integers(min_value=0, max_value=23))
4869 minute = d.draw(integers(min_value=0, max_value=59))
4870 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4872 year + (2000 if year < 50 else 1900),
4879 if d.draw(booleans()):
4881 seconds = d.draw(integers(min_value=0, max_value=59))
4882 data += "%02d" % seconds
4883 dt += timedelta(seconds=seconds)
4884 if d.draw(booleans()):
4888 offset_hour = d.draw(integers(min_value=0, max_value=13))
4889 offset_minute = d.draw(integers(min_value=0, max_value=59))
4890 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4891 if d.draw(booleans()):
4897 data += "%02d%02d" % (offset_hour, offset_minute)
4898 data = data.encode("ascii")
4899 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4900 obj = UTCTime().decod(data_der, ctx={"bered": True})
4901 self.assertEqual(obj, dt)
4902 self.assertEqual(obj.todatetime(), dt)
4903 self.assertEqual(obj.ber_encoded, not dered)
4904 self.assertEqual(obj.bered, not dered)
4905 self.assertEqual(obj.ber_raw, None if dered else data)
4906 self.assertEqual(obj.encode() == data_der, dered)
4911 def test_invalid_ber(self):
4952 b"0001020304+0000Z",
4961 with self.assertRaises(DecodeError):
4962 UTCTime(data, ctx={"bered": True})
4963 data = data[:8] + data[8+2:]
4964 with self.assertRaises(DecodeError):
4965 UTCTime(data, ctx={"bered": True})
5010 b"000102030405+000",
5011 b"000102030405+000Z",
5012 b"000102030405+0000Z",
5013 b"000102030405+-101",
5014 b"000102030405+01-1",
5015 b"000102030405+0060",
5016 b"000102030405+1401",
5017 b"500101000002+0003",
5019 with self.assertRaises(DecodeError):
5020 UTCTime(data, ctx={"bered": True})
5022 @given(integers(min_value=0, max_value=49))
5023 def test_pre50(self, year):
5025 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5029 @given(integers(min_value=50, max_value=99))
5030 def test_post50(self, year):
5032 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5038 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5039 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5041 binary(min_size=1, max_size=1),
5043 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5044 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5047 def test_junk(self, part0, part1, part2):
5048 junk = part0 + part1 + part2
5049 assume(not (set(junk) <= set(digits.encode("ascii"))))
5050 with self.assertRaises(DecodeError):
5052 UTCTime.tag_default +
5053 len_encode(len(junk)) +
5059 def tlv_value_strategy(draw):
5060 tag_num = draw(integers(min_value=1))
5061 data = draw(binary())
5062 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5066 def any_values_strategy(draw, do_expl=False):
5067 value = draw(one_of(none(), tlv_value_strategy()))
5070 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5071 optional = draw(one_of(none(), booleans()))
5073 draw(integers(min_value=0)),
5074 draw(integers(min_value=0)),
5075 draw(integers(min_value=0)),
5077 return (value, expl, optional, _decoded)
5080 class AnyInherited(Any):
5084 class TestAny(CommonMixin, TestCase):
5087 def test_invalid_value_type(self):
5088 with self.assertRaises(InvalidValueType) as err:
5093 def test_optional(self, optional):
5094 obj = Any(optional=optional)
5095 self.assertEqual(obj.optional, optional)
5097 @given(tlv_value_strategy())
5098 def test_ready(self, value):
5100 self.assertFalse(obj.ready)
5103 pprint(obj, big_blobs=True, with_decode_path=True)
5104 with self.assertRaises(ObjNotReady) as err:
5107 with self.assertRaises(ObjNotReady) as err:
5110 self.assertTrue(obj.ready)
5113 pprint(obj, big_blobs=True, with_decode_path=True)
5116 def test_basic(self, value):
5117 integer_encoded = Integer(value).encode()
5119 Any(integer_encoded),
5120 Any(Integer(value)),
5121 Any(Any(Integer(value))),
5123 self.assertSequenceEqual(bytes(obj), integer_encoded)
5125 obj.decode(obj.encode())[0].vlen,
5126 len(integer_encoded),
5130 pprint(obj, big_blobs=True, with_decode_path=True)
5131 self.assertSequenceEqual(obj.encode(), integer_encoded)
5133 @given(tlv_value_strategy(), tlv_value_strategy())
5134 def test_comparison(self, value1, value2):
5135 for klass in (Any, AnyInherited):
5136 obj1 = klass(value1)
5137 obj2 = klass(value2)
5138 self.assertEqual(obj1 == obj2, value1 == value2)
5139 self.assertEqual(obj1 != obj2, value1 != value2)
5140 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5142 @given(data_strategy())
5143 def test_call(self, d):
5144 for klass in (Any, AnyInherited):
5150 ) = d.draw(any_values_strategy())
5151 obj_initial = klass(
5154 optional_initial or False,
5162 ) = d.draw(any_values_strategy(do_expl=True))
5163 obj = obj_initial(value, expl, optional)
5165 value_expected = None if value is None else value
5166 self.assertEqual(obj, value_expected)
5167 self.assertEqual(obj.expl_tag, expl or expl_initial)
5168 if obj.default is None:
5169 optional = optional_initial if optional is None else optional
5170 optional = False if optional is None else optional
5171 self.assertEqual(obj.optional, optional)
5173 def test_simultaneous_impl_expl(self):
5174 # override it, as Any does not have implicit tag
5177 def test_decoded(self):
5178 # override it, as Any does not have implicit tag
5181 @given(any_values_strategy())
5182 def test_copy(self, values):
5183 for klass in (Any, AnyInherited):
5184 obj = klass(*values)
5185 for copy_func in copy_funcs:
5186 obj_copied = copy_func(obj)
5187 self.assert_copied_basic_fields(obj, obj_copied)
5188 self.assertEqual(obj._value, obj_copied._value)
5190 @given(binary().map(OctetString))
5191 def test_stripped(self, value):
5193 with self.assertRaises(NotEnoughData):
5194 obj.decode(obj.encode()[:-1])
5197 tlv_value_strategy(),
5198 integers(min_value=1).map(tag_ctxc),
5200 def test_stripped_expl(self, value, tag_expl):
5201 obj = Any(value, expl=tag_expl)
5202 with self.assertRaises(NotEnoughData):
5203 obj.decode(obj.encode()[:-1])
5206 integers(min_value=31),
5207 integers(min_value=0),
5210 def test_bad_tag(self, tag, offset, decode_path):
5211 with self.assertRaises(DecodeError) as err:
5213 tag_encode(tag)[:-1],
5215 decode_path=decode_path,
5218 self.assertEqual(err.exception.offset, offset)
5219 self.assertEqual(err.exception.decode_path, decode_path)
5222 integers(min_value=128),
5223 integers(min_value=0),
5226 def test_bad_len(self, l, offset, decode_path):
5227 with self.assertRaises(DecodeError) as err:
5229 Any.tag_default + len_encode(l)[:-1],
5231 decode_path=decode_path,
5234 self.assertEqual(err.exception.offset, offset)
5235 self.assertEqual(err.exception.decode_path, decode_path)
5237 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5239 any_values_strategy(),
5240 integers().map(lambda x: Integer(x).encode()),
5241 integers(min_value=1).map(tag_ctxc),
5242 integers(min_value=0),
5246 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5247 for klass in (Any, AnyInherited):
5248 _, _, optional, _decoded = values
5249 obj = klass(value=value, optional=optional, _decoded=_decoded)
5252 pprint(obj, big_blobs=True, with_decode_path=True)
5253 self.assertFalse(obj.expled)
5254 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5255 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5256 obj_encoded = obj.encode()
5257 self.assertEqual(encode2pass(obj), obj_encoded)
5258 obj_expled = obj(value, expl=tag_expl)
5259 self.assertTrue(obj_expled.expled)
5260 tag_class, _, tag_num = tag_decode(tag_expl)
5261 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5263 list(obj_expled.pps())
5264 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5265 obj_expled_encoded = obj_expled.encode()
5266 ctx_copied = deepcopy(ctx_dummy)
5267 obj_decoded, tail = obj_expled.decode(
5268 obj_expled_encoded + tail_junk,
5272 self.assertDictEqual(ctx_copied, ctx_dummy)
5274 list(obj_decoded.pps())
5275 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5276 self.assertEqual(tail, tail_junk)
5277 self.assertEqual(obj_decoded, obj_expled)
5278 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5279 self.assertEqual(bytes(obj_decoded), bytes(obj))
5280 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5281 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5282 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5284 obj_decoded.expl_llen,
5285 len(len_encode(len(obj_encoded))),
5287 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5288 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5291 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5293 self.assertEqual(obj_decoded.expl_offset, offset)
5294 self.assertEqual(obj_decoded.tlen, 0)
5295 self.assertEqual(obj_decoded.llen, 0)
5296 self.assertEqual(obj_decoded.vlen, len(value))
5297 assert_exceeding_data(
5299 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5303 evgens = list(obj_expled.decode_evgen(
5304 obj_expled_encoded + tail_junk,
5306 decode_path=decode_path,
5309 self.assertEqual(len(evgens), 1)
5310 _decode_path, obj, tail = evgens[0]
5311 self.assertSequenceEqual(tail, tail_junk)
5312 self.assertEqual(_decode_path, decode_path)
5313 self.assertEqual(obj.expl_offset, offset)
5318 integers(min_value=1).map(tag_ctxc),
5319 integers(min_value=0, max_value=3),
5320 integers(min_value=0),
5324 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5325 chunk = Boolean(False, expl=expl).encode()
5327 OctetString.tag_default +
5329 b"".join([chunk] * chunks) +
5332 with self.assertRaises(LenIndefForm):
5336 decode_path=decode_path,
5338 obj, tail = Any().decode(
5341 decode_path=decode_path,
5342 ctx={"bered": True},
5344 self.assertSequenceEqual(tail, junk)
5345 self.assertEqual(obj.offset, offset)
5346 self.assertEqual(obj.tlvlen, len(encoded))
5347 self.assertTrue(obj.lenindef)
5348 self.assertFalse(obj.ber_encoded)
5349 self.assertTrue(obj.bered)
5351 self.assertTrue(obj.lenindef)
5352 self.assertFalse(obj.ber_encoded)
5353 self.assertTrue(obj.bered)
5356 pprint(obj, big_blobs=True, with_decode_path=True)
5357 with self.assertRaises(NotEnoughData) as err:
5361 decode_path=decode_path,
5362 ctx={"bered": True},
5364 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5365 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5367 class SeqOf(SequenceOf):
5368 schema = Boolean(expl=expl)
5370 class Seq(Sequence):
5372 ("type", ObjectIdentifier(defines=((("value",), {
5373 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5378 ("type", ObjectIdentifier("1.2.3")),
5379 ("value", Any(encoded)),
5381 seq_encoded = seq.encode()
5382 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5383 self.assertIsNotNone(seq_decoded["value"].defined)
5385 list(seq_decoded.pps())
5386 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5387 self.assertTrue(seq_decoded.bered)
5388 self.assertFalse(seq_decoded["type"].bered)
5389 self.assertTrue(seq_decoded["value"].bered)
5391 chunk = chunk[:-1] + b"\x01"
5392 chunks = b"".join([chunk] * (chunks + 1))
5393 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5395 ("type", ObjectIdentifier("1.2.3")),
5396 ("value", Any(encoded)),
5398 seq_encoded = seq.encode()
5399 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5400 self.assertIsNotNone(seq_decoded["value"].defined)
5402 list(seq_decoded.pps())
5403 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5404 self.assertTrue(seq_decoded.bered)
5405 self.assertFalse(seq_decoded["type"].bered)
5406 self.assertTrue(seq_decoded["value"].bered)
5410 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5412 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5413 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5415 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5416 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5418 min_size=len(names),
5419 max_size=len(names),
5422 (name, Integer(**tag_kwargs))
5423 for name, tag_kwargs in zip(names, tags)
5426 if value_required or draw(booleans()):
5427 value = draw(tuples(
5428 sampled_from([name for name, _ in schema]),
5429 integers().map(Integer),
5433 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5434 default = draw(one_of(
5436 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5438 optional = draw(one_of(none(), booleans()))
5440 draw(integers(min_value=0)),
5441 draw(integers(min_value=0)),
5442 draw(integers(min_value=0)),
5444 return (schema, value, expl, default, optional, _decoded)
5447 class ChoiceInherited(Choice):
5451 class TestChoice(CommonMixin, TestCase):
5453 schema = (("whatever", Boolean()),)
5456 def test_schema_required(self):
5457 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5460 def test_impl_forbidden(self):
5461 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5462 Choice(impl=b"whatever")
5464 def test_invalid_value_type(self):
5465 with self.assertRaises(InvalidValueType) as err:
5466 self.base_klass(123)
5468 with self.assertRaises(ObjUnknown) as err:
5469 self.base_klass(("whenever", Boolean(False)))
5471 with self.assertRaises(InvalidValueType) as err:
5472 self.base_klass(("whatever", Integer(123)))
5476 def test_optional(self, optional):
5477 obj = self.base_klass(
5478 default=self.base_klass(("whatever", Boolean(False))),
5481 self.assertTrue(obj.optional)
5484 def test_ready(self, value):
5485 obj = self.base_klass()
5486 self.assertFalse(obj.ready)
5489 pprint(obj, big_blobs=True, with_decode_path=True)
5490 self.assertIsNone(obj["whatever"])
5491 with self.assertRaises(ObjNotReady) as err:
5494 with self.assertRaises(ObjNotReady) as err:
5496 obj["whatever"] = Boolean()
5497 self.assertFalse(obj.ready)
5500 pprint(obj, big_blobs=True, with_decode_path=True)
5501 obj["whatever"] = Boolean(value)
5502 self.assertTrue(obj.ready)
5505 pprint(obj, big_blobs=True, with_decode_path=True)
5507 @given(booleans(), booleans())
5508 def test_comparison(self, value1, value2):
5509 class WahlInherited(self.base_klass):
5511 for klass in (self.base_klass, WahlInherited):
5512 obj1 = klass(("whatever", Boolean(value1)))
5513 obj2 = klass(("whatever", Boolean(value2)))
5514 self.assertEqual(obj1 == obj2, value1 == value2)
5515 self.assertEqual(obj1 != obj2, value1 != value2)
5516 self.assertEqual(obj1 == obj2._value, value1 == value2)
5517 self.assertFalse(obj1 == obj2._value[1])
5519 @given(data_strategy())
5520 def test_call(self, d):
5521 for klass in (Choice, ChoiceInherited):
5529 ) = d.draw(choice_values_strategy())
5532 schema = schema_initial
5534 value=value_initial,
5536 default=default_initial,
5537 optional=optional_initial or False,
5538 _decoded=_decoded_initial,
5547 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5548 obj = obj_initial(value, expl, default, optional)
5550 value_expected = default if value is None else value
5552 default_initial if value_expected is None
5555 self.assertEqual(obj.choice, value_expected[0])
5556 self.assertEqual(obj.value, int(value_expected[1]))
5557 self.assertEqual(obj.expl_tag, expl or expl_initial)
5558 default_expect = default_initial if default is None else default
5559 if default_expect is not None:
5560 self.assertEqual(obj.default.choice, default_expect[0])
5561 self.assertEqual(obj.default.value, int(default_expect[1]))
5562 if obj.default is None:
5563 optional = optional_initial if optional is None else optional
5564 optional = False if optional is None else optional
5567 self.assertEqual(obj.optional, optional)
5568 self.assertEqual(obj.specs, obj_initial.specs)
5570 def test_simultaneous_impl_expl(self):
5571 # override it, as Any does not have implicit tag
5574 def test_decoded(self):
5575 # override it, as Any does not have implicit tag
5578 @given(choice_values_strategy())
5579 def test_copy(self, values):
5580 _schema, value, expl, default, optional, _decoded = values
5582 class Wahl(self.base_klass):
5584 register_class(Wahl)
5589 optional=optional or False,
5592 for copy_func in copy_funcs:
5593 obj_copied = copy_func(obj)
5594 self.assertIsNone(obj.tag)
5595 self.assertIsNone(obj_copied.tag)
5596 # hack for assert_copied_basic_fields
5597 obj.tag = "whatever"
5598 obj_copied.tag = "whatever"
5599 self.assert_copied_basic_fields(obj, obj_copied)
5601 self.assertEqual(obj._value, obj_copied._value)
5602 self.assertEqual(obj.specs, obj_copied.specs)
5605 def test_stripped(self, value):
5606 obj = self.base_klass(("whatever", Boolean(value)))
5607 with self.assertRaises(NotEnoughData):
5608 obj.decode(obj.encode()[:-1])
5612 integers(min_value=1).map(tag_ctxc),
5614 def test_stripped_expl(self, value, tag_expl):
5615 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5616 with self.assertRaises(NotEnoughData):
5617 obj.decode(obj.encode()[:-1])
5619 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5620 @given(data_strategy())
5621 def test_symmetric(self, d):
5622 _schema, value, _, default, optional, _decoded = d.draw(
5623 choice_values_strategy(value_required=True)
5625 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5626 offset = d.draw(integers(min_value=0))
5627 tail_junk = d.draw(binary(max_size=5))
5628 decode_path = d.draw(decode_path_strat)
5630 class Wahl(self.base_klass):
5640 pprint(obj, big_blobs=True, with_decode_path=True)
5641 self.assertFalse(obj.expled)
5642 self.assertEqual(obj.tag_order, obj.value.tag_order)
5643 obj_encoded = obj.encode()
5644 self.assertEqual(encode2pass(obj), obj_encoded)
5645 obj_expled = obj(value, expl=tag_expl)
5646 self.assertTrue(obj_expled.expled)
5647 tag_class, _, tag_num = tag_decode(tag_expl)
5648 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5650 list(obj_expled.pps())
5651 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5652 obj_expled_encoded = obj_expled.encode()
5653 ctx_copied = deepcopy(ctx_dummy)
5654 obj_decoded, tail = obj_expled.decode(
5655 obj_expled_encoded + tail_junk,
5659 self.assertDictEqual(ctx_copied, ctx_dummy)
5661 list(obj_decoded.pps())
5662 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5663 self.assertEqual(tail, tail_junk)
5664 self.assertEqual(obj_decoded, obj_expled)
5665 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5666 self.assertEqual(obj_decoded.value, obj_expled.value)
5667 self.assertEqual(obj_decoded.choice, obj.choice)
5668 self.assertEqual(obj_decoded.value, obj.value)
5669 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5670 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5671 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5673 obj_decoded.expl_llen,
5674 len(len_encode(len(obj_encoded))),
5676 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5677 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5680 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5682 self.assertEqual(obj_decoded.expl_offset, offset)
5683 self.assertSequenceEqual(
5685 obj_decoded.value.fulloffset - offset:
5686 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5690 assert_exceeding_data(
5692 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5696 evgens = list(obj_expled.decode_evgen(
5697 obj_expled_encoded + tail_junk,
5699 decode_path=decode_path,
5702 self.assertEqual(len(evgens), 2)
5703 _decode_path, obj, tail = evgens[0]
5704 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5705 _decode_path, obj, tail = evgens[1]
5706 self.assertSequenceEqual(tail, tail_junk)
5707 self.assertEqual(_decode_path, decode_path)
5708 self.assertEqual(obj.expl_offset, offset)
5713 def test_set_get(self, value):
5716 ("erste", Boolean()),
5717 ("zweite", Integer()),
5720 with self.assertRaises(ObjUnknown) as err:
5721 obj["whatever"] = "whenever"
5722 with self.assertRaises(InvalidValueType) as err:
5723 obj["zweite"] = Boolean(False)
5724 obj["zweite"] = Integer(value)
5726 with self.assertRaises(ObjUnknown) as err:
5729 self.assertIsNone(obj["erste"])
5730 self.assertEqual(obj["zweite"], Integer(value))
5732 def test_tag_mismatch(self):
5735 ("erste", Boolean()),
5737 int_encoded = Integer(123).encode()
5738 bool_encoded = Boolean(False).encode()
5740 obj.decode(bool_encoded)
5741 with self.assertRaises(TagMismatch):
5742 obj.decode(int_encoded)
5744 def test_tag_mismatch_underlying(self):
5745 class SeqOfBoolean(SequenceOf):
5748 class SeqOfInteger(SequenceOf):
5753 ("erste", SeqOfBoolean()),
5756 int_encoded = SeqOfInteger((Integer(123),)).encode()
5757 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5759 obj.decode(bool_encoded)
5760 with self.assertRaises(TagMismatch) as err:
5761 obj.decode(int_encoded)
5762 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5766 def seq_values_strategy(draw, seq_klass, do_expl=False):
5768 if draw(booleans()):
5770 value._value = draw(dictionaries(
5773 booleans().map(Boolean),
5774 integers().map(Integer),
5778 if draw(booleans()):
5779 schema = list(draw(dictionaries(
5782 booleans().map(Boolean),
5783 integers().map(Integer),
5789 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5791 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5793 if draw(booleans()):
5794 default = seq_klass()
5795 default._value = draw(dictionaries(
5798 booleans().map(Boolean),
5799 integers().map(Integer),
5802 optional = draw(one_of(none(), booleans()))
5804 draw(integers(min_value=0)),
5805 draw(integers(min_value=0)),
5806 draw(integers(min_value=0)),
5808 return (value, schema, impl, expl, default, optional, _decoded)
5812 def sequence_strategy(draw, seq_klass):
5813 inputs = draw(lists(
5815 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5816 tuples(just(Integer), integers(), one_of(none(), integers())),
5821 integers(min_value=1),
5822 min_size=len(inputs),
5823 max_size=len(inputs),
5826 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5827 for tag, expled in zip(tags, draw(lists(
5829 min_size=len(inputs),
5830 max_size=len(inputs),
5834 for i, optional in enumerate(draw(lists(
5835 sampled_from(("required", "optional", "empty")),
5836 min_size=len(inputs),
5837 max_size=len(inputs),
5839 if optional in ("optional", "empty"):
5840 inits[i]["optional"] = True
5841 if optional == "empty":
5843 empties = set(empties)
5844 names = list(draw(sets(
5846 min_size=len(inputs),
5847 max_size=len(inputs),
5850 for i, (klass, value, default) in enumerate(inputs):
5851 schema.append((names[i], klass(default=default, **inits[i])))
5852 seq_name = draw(text_letters())
5853 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5856 for i, (klass, value, default) in enumerate(inputs):
5863 "default_value": None if spec.default is None else default,
5867 expect["optional"] = True
5869 expect["presented"] = True
5870 expect["value"] = value
5872 expect["optional"] = True
5873 if default is not None and default == value:
5874 expect["presented"] = False
5875 seq[name] = klass(value)
5876 expects.append(expect)
5881 def sequences_strategy(draw, seq_klass):
5882 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5884 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5885 for tag, expled in zip(tags, draw(lists(
5892 i for i, is_default in enumerate(draw(lists(
5898 names = list(draw(sets(
5903 seq_expectses = draw(lists(
5904 sequence_strategy(seq_klass=seq_klass),
5908 seqs = [seq for seq, _ in seq_expectses]
5910 for i, (name, seq) in enumerate(zip(names, seqs)):
5913 seq(default=(seq if i in defaulted else None), **inits[i]),
5915 seq_name = draw(text_letters())
5916 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5919 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5922 "expects": expects_inner,
5925 seq_outer[name] = seq_inner
5926 if seq_outer.specs[name].default is None:
5927 expect["presented"] = True
5928 expect_outers.append(expect)
5929 return seq_outer, expect_outers
5932 class SeqMixing(object):
5933 def test_invalid_value_type(self):
5934 with self.assertRaises(InvalidValueType) as err:
5935 self.base_klass(123)
5938 def test_invalid_value_type_set(self):
5939 class Seq(self.base_klass):
5940 schema = (("whatever", Boolean()),)
5942 with self.assertRaises(InvalidValueType) as err:
5943 seq["whatever"] = Integer(123)
5947 def test_optional(self, optional):
5948 obj = self.base_klass(default=self.base_klass(), optional=optional)
5949 self.assertTrue(obj.optional)
5951 @given(data_strategy())
5952 def test_ready(self, d):
5954 str(i): v for i, v in enumerate(d.draw(lists(
5961 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5968 for name in d.draw(permutations(
5969 list(ready.keys()) + list(non_ready.keys()),
5971 schema_input.append((name, Boolean()))
5973 class Seq(self.base_klass):
5974 schema = tuple(schema_input)
5976 for name in ready.keys():
5978 seq[name] = Boolean()
5979 self.assertFalse(seq.ready)
5982 pprint(seq, big_blobs=True, with_decode_path=True)
5983 for name, value in ready.items():
5984 seq[name] = Boolean(value)
5985 self.assertFalse(seq.ready)
5988 pprint(seq, big_blobs=True, with_decode_path=True)
5989 with self.assertRaises(ObjNotReady) as err:
5992 with self.assertRaises(ObjNotReady) as err:
5994 for name, value in non_ready.items():
5995 seq[name] = Boolean(value)
5996 self.assertTrue(seq.ready)
5999 pprint(seq, big_blobs=True, with_decode_path=True)
6001 @given(data_strategy())
6002 def test_call(self, d):
6003 class SeqInherited(self.base_klass):
6005 for klass in (self.base_klass, SeqInherited):
6014 ) = d.draw(seq_values_strategy(seq_klass=klass))
6015 obj_initial = klass(
6021 optional_initial or False,
6032 ) = d.draw(seq_values_strategy(
6034 do_expl=impl_initial is None,
6036 obj = obj_initial(value, impl, expl, default, optional)
6037 value_expected = default if value is None else value
6039 default_initial if value_expected is None
6042 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
6043 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6044 self.assertEqual(obj.expl_tag, expl or expl_initial)
6046 {} if obj.default is None else obj.default._value,
6047 getattr(default_initial if default is None else default, "_value", {}),
6049 if obj.default is None:
6050 optional = optional_initial if optional is None else optional
6051 optional = False if optional is None else optional
6054 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6055 self.assertEqual(obj.optional, optional)
6057 @given(data_strategy())
6058 def test_copy(self, d):
6059 class SeqInherited(self.base_klass):
6061 register_class(SeqInherited)
6062 for klass in (self.base_klass, SeqInherited):
6063 values = d.draw(seq_values_strategy(seq_klass=klass))
6064 obj = klass(*values)
6065 for copy_func in copy_funcs:
6066 obj_copied = copy_func(obj)
6067 self.assert_copied_basic_fields(obj, obj_copied)
6068 self.assertEqual(obj.specs, obj_copied.specs)
6069 self.assertEqual(obj._value, obj_copied._value)
6071 @given(data_strategy())
6072 def test_stripped(self, d):
6073 value = d.draw(integers())
6074 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6076 class Seq(self.base_klass):
6078 schema = (("whatever", Integer()),)
6080 seq["whatever"] = Integer(value)
6081 with self.assertRaises(NotEnoughData):
6082 seq.decode(seq.encode()[:-1])
6084 @given(data_strategy())
6085 def test_stripped_expl(self, d):
6086 value = d.draw(integers())
6087 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6089 class Seq(self.base_klass):
6091 schema = (("whatever", Integer()),)
6093 seq["whatever"] = Integer(value)
6094 with self.assertRaises(NotEnoughData):
6095 seq.decode(seq.encode()[:-1])
6097 @given(integers(min_value=3), binary(min_size=2))
6098 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6099 junk = tag_encode(junk_tag_num) + junk
6101 _, _, len_encoded = tag_strip(memoryview(junk))
6102 len_decode(len_encoded)
6108 class Seq(self.base_klass):
6110 ("whatever", Integer()),
6112 ("whenever", Integer()),
6115 seq["whatever"] = Integer(123)
6116 seq["junk"] = Any(junk)
6117 seq["whenever"] = Integer(123)
6118 with self.assertRaises(DecodeError):
6119 seq.decode(seq.encode())
6122 integers(min_value=31),
6123 integers(min_value=0),
6126 def test_bad_tag(self, tag, offset, decode_path):
6127 with self.assertRaises(DecodeError) as err:
6128 self.base_klass().decode(
6129 tag_encode(tag)[:-1],
6131 decode_path=decode_path,
6134 self.assertEqual(err.exception.offset, offset)
6135 self.assertEqual(err.exception.decode_path, decode_path)
6138 integers(min_value=128),
6139 integers(min_value=0),
6142 def test_bad_len(self, l, offset, decode_path):
6143 with self.assertRaises(DecodeError) as err:
6144 self.base_klass().decode(
6145 self.base_klass.tag_default + len_encode(l)[:-1],
6147 decode_path=decode_path,
6150 self.assertEqual(err.exception.offset, offset)
6151 self.assertEqual(err.exception.decode_path, decode_path)
6153 def _assert_expects(self, seq, expects):
6154 for expect in expects:
6156 seq.specs[expect["name"]].optional,
6159 if expect["default_value"] is not None:
6161 seq.specs[expect["name"]].default,
6162 expect["default_value"],
6164 if expect["presented"]:
6165 self.assertIn(expect["name"], seq)
6166 self.assertEqual(seq[expect["name"]], expect["value"])
6168 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6169 @given(data_strategy())
6170 def test_symmetric(self, d):
6171 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6172 tail_junk = d.draw(binary(max_size=5))
6173 decode_path = d.draw(decode_path_strat)
6174 self.assertTrue(seq.ready)
6175 self.assertFalse(seq.decoded)
6176 self._assert_expects(seq, expects)
6179 pprint(seq, big_blobs=True, with_decode_path=True)
6180 self.assertTrue(seq.ready)
6181 seq_encoded = seq.encode()
6182 self.assertEqual(encode2pass(seq), seq_encoded)
6183 seq_encoded_cer = encode_cer(seq)
6184 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6185 self.assertSequenceEqual(
6186 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6189 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6190 self.assertFalse(seq_decoded.lenindef)
6191 self.assertFalse(seq_decoded.ber_encoded)
6192 self.assertFalse(seq_decoded.bered)
6194 t, _, lv = tag_strip(seq_encoded)
6195 _, _, v = len_decode(lv)
6196 seq_encoded_lenindef = t + LENINDEF + v + EOC
6197 with self.assertRaises(DecodeError):
6198 seq.decode(seq_encoded_lenindef)
6199 ctx_copied = deepcopy(ctx_dummy)
6200 ctx_copied["bered"] = True
6201 seq_decoded_lenindef, tail_lenindef = seq.decode(
6202 seq_encoded_lenindef + tail_junk,
6205 del ctx_copied["bered"]
6206 self.assertDictEqual(ctx_copied, ctx_dummy)
6207 self.assertTrue(seq_decoded_lenindef.lenindef)
6208 self.assertTrue(seq_decoded_lenindef.bered)
6209 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6210 self.assertTrue(seq_decoded_lenindef.lenindef)
6211 self.assertTrue(seq_decoded_lenindef.bered)
6212 with self.assertRaises(DecodeError):
6213 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6214 with self.assertRaises(DecodeError):
6215 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6216 repr(seq_decoded_lenindef)
6217 list(seq_decoded_lenindef.pps())
6218 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6219 self.assertTrue(seq_decoded_lenindef.ready)
6221 for decoded, decoded_tail, encoded in (
6222 (seq_decoded, tail, seq_encoded),
6223 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6225 self.assertEqual(decoded_tail, tail_junk)
6226 self._assert_expects(decoded, expects)
6227 self.assertEqual(seq, decoded)
6228 self.assertEqual(decoded.encode(), seq_encoded)
6229 self.assertEqual(decoded.tlvlen, len(encoded))
6230 for expect in expects:
6231 if not expect["presented"]:
6232 self.assertNotIn(expect["name"], decoded)
6234 self.assertIn(expect["name"], decoded)
6235 obj = decoded[expect["name"]]
6236 self.assertTrue(obj.decoded)
6237 offset = obj.expl_offset if obj.expled else obj.offset
6238 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6239 self.assertSequenceEqual(
6240 seq_encoded[offset:offset + tlvlen],
6244 evgens = list(seq.decode_evgen(
6245 encoded + decoded_tail,
6246 decode_path=decode_path,
6247 ctx={"bered": True},
6249 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6250 for _decode_path, obj, _ in evgens[:-1]:
6251 self.assertEqual(_decode_path[:-1], decode_path)
6254 _decode_path, obj, tail = evgens[-1]
6255 self.assertEqual(_decode_path, decode_path)
6259 assert_exceeding_data(
6261 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6265 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6266 @given(data_strategy())
6267 def test_symmetric_with_seq(self, d):
6268 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6269 self.assertTrue(seq.ready)
6270 seq_encoded = seq.encode()
6271 self.assertEqual(encode2pass(seq), seq_encoded)
6272 seq_decoded, tail = seq.decode(seq_encoded)
6273 self.assertEqual(tail, b"")
6274 self.assertTrue(seq.ready)
6275 self.assertEqual(seq, seq_decoded)
6276 self.assertEqual(seq_decoded.encode(), seq_encoded)
6277 for expect_outer in expect_outers:
6278 if not expect_outer["presented"]:
6279 self.assertNotIn(expect_outer["name"], seq_decoded)
6281 self.assertIn(expect_outer["name"], seq_decoded)
6282 obj = seq_decoded[expect_outer["name"]]
6283 self.assertTrue(obj.decoded)
6284 offset = obj.expl_offset if obj.expled else obj.offset
6285 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6286 self.assertSequenceEqual(
6287 seq_encoded[offset:offset + tlvlen],
6290 self._assert_expects(obj, expect_outer["expects"])
6292 @given(data_strategy())
6293 def test_default_disappears(self, d):
6294 _schema = list(d.draw(dictionaries(
6296 sets(integers(), min_size=2, max_size=2),
6300 class Seq(self.base_klass):
6302 (n, Integer(default=d))
6303 for n, (_, d) in _schema
6306 for name, (value, _) in _schema:
6307 seq[name] = Integer(value)
6308 self.assertEqual(len(seq._value), len(_schema))
6309 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6310 self.assertGreater(len(seq.encode()), len(empty_seq))
6311 for name, (_, default) in _schema:
6312 seq[name] = Integer(default)
6313 self.assertEqual(len(seq._value), 0)
6314 self.assertSequenceEqual(seq.encode(), empty_seq)
6316 @given(data_strategy())
6317 def test_encoded_default_not_accepted(self, d):
6318 _schema = list(d.draw(dictionaries(
6323 tags = [tag_encode(tag) for tag in d.draw(sets(
6324 integers(min_value=1),
6325 min_size=len(_schema),
6326 max_size=len(_schema),
6330 schema = (("int", Integer()),)
6332 class SeqWithoutDefault(self.base_klass):
6335 for (n, _), t in zip(_schema, tags)
6337 seq_without_default = SeqWithoutDefault()
6338 for name, value in _schema:
6339 seq_without_default[name] = Wahl(("int", Integer(value)))
6340 seq_encoded = seq_without_default.encode()
6341 seq_without_default.decode(seq_encoded)
6343 len(list(seq_without_default.decode_evgen(seq_encoded))),
6344 len(_schema) * 2 + 1,
6347 class SeqWithDefault(self.base_klass):
6349 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6350 for (n, v), t in zip(_schema, tags)
6352 seq_with_default = SeqWithDefault()
6353 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6354 seq_with_default.decode(seq_encoded)
6355 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6356 list(seq_with_default.decode_evgen(seq_encoded))
6357 for ctx in ({"bered": True}, {"allow_default_values": True}):
6358 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6359 self.assertTrue(seq_decoded.ber_encoded)
6360 self.assertTrue(seq_decoded.bered)
6361 seq_decoded = copy(seq_decoded)
6362 self.assertTrue(seq_decoded.ber_encoded)
6363 self.assertTrue(seq_decoded.bered)
6364 for name, value in _schema:
6365 self.assertEqual(seq_decoded[name], seq_with_default[name])
6366 self.assertEqual(seq_decoded[name].value, value)
6368 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6372 seq_without_default = SeqWithoutDefault()
6373 for name, value in _schema:
6374 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6375 seq_encoded = seq_without_default.encode()
6376 seq_with_default.decode(seq_encoded)
6378 len(list(seq_with_default.decode_evgen(seq_encoded))),
6382 @given(data_strategy())
6383 def test_missing_from_spec(self, d):
6384 names = list(d.draw(sets(text_letters(), min_size=2)))
6385 tags = [tag_encode(tag) for tag in d.draw(sets(
6386 integers(min_value=1),
6387 min_size=len(names),
6388 max_size=len(names),
6390 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6392 class SeqFull(self.base_klass):
6393 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6394 seq_full = SeqFull()
6395 for i, name in enumerate(names):
6396 seq_full[name] = Integer(i)
6397 seq_encoded = seq_full.encode()
6398 altered = names_tags[:-2] + names_tags[-1:]
6400 class SeqMissing(self.base_klass):
6401 schema = [(n, Integer(impl=t)) for n, t in altered]
6402 seq_missing = SeqMissing()
6403 with self.assertRaises(TagMismatch):
6404 seq_missing.decode(seq_encoded)
6405 with self.assertRaises(TagMismatch):
6406 list(seq_missing.decode_evgen(seq_encoded))
6408 def test_bered(self):
6409 class Seq(self.base_klass):
6410 schema = (("underlying", Boolean()),)
6411 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6412 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6413 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6414 self.assertFalse(decoded.ber_encoded)
6415 self.assertFalse(decoded.lenindef)
6416 self.assertTrue(decoded.bered)
6417 decoded = copy(decoded)
6418 self.assertFalse(decoded.ber_encoded)
6419 self.assertFalse(decoded.lenindef)
6420 self.assertTrue(decoded.bered)
6422 class Seq(self.base_klass):
6423 schema = (("underlying", OctetString()),)
6425 tag_encode(form=TagFormConstructed, num=4) +
6427 OctetString(b"whatever").encode() +
6430 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6431 with self.assertRaises(DecodeError):
6432 Seq().decode(encoded)
6433 with self.assertRaises(DecodeError):
6434 list(Seq().decode_evgen(encoded))
6435 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6436 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6437 self.assertFalse(decoded.ber_encoded)
6438 self.assertFalse(decoded.lenindef)
6439 self.assertTrue(decoded.bered)
6440 decoded = copy(decoded)
6441 self.assertFalse(decoded.ber_encoded)
6442 self.assertFalse(decoded.lenindef)
6443 self.assertTrue(decoded.bered)
6446 class TestSequence(SeqMixing, CommonMixin, TestCase):
6447 base_klass = Sequence
6453 def test_remaining(self, value, junk):
6454 class Seq(Sequence):
6456 ("whatever", Integer()),
6458 int_encoded = Integer(value).encode()
6460 Sequence.tag_default,
6461 len_encode(len(int_encoded + junk)),
6464 with assertRaisesRegex(self, DecodeError, "remaining"):
6465 Seq().decode(junked)
6467 @given(sets(text_letters(), min_size=2))
6468 def test_obj_unknown(self, names):
6469 missing = names.pop()
6471 class Seq(Sequence):
6472 schema = [(n, Boolean()) for n in names]
6474 with self.assertRaises(ObjUnknown) as err:
6477 with self.assertRaises(ObjUnknown) as err:
6478 seq[missing] = Boolean()
6481 def test_x690_vector(self):
6482 class Seq(Sequence):
6484 ("name", IA5String()),
6487 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6488 self.assertEqual(seq["name"], "Smith")
6489 self.assertEqual(seq["ok"], True)
6492 class TestSet(SeqMixing, CommonMixin, TestCase):
6495 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6496 @given(data_strategy())
6497 def test_sorted(self, d):
6498 class DummySeq(Sequence):
6499 schema = (("null", Null()),)
6501 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6502 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6503 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6504 tag_nums -= set([dummy_seq_tag_num])
6505 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6506 _schema.append(("seq", DummySeq()))
6509 schema = d.draw(permutations(_schema))
6511 for name, _ in _schema:
6513 seq[name] = OctetString(name.encode("ascii"))
6514 seq["seq"] = DummySeq((("null", Null()),))
6516 seq_encoded = seq.encode()
6517 seq_decoded, _ = seq.decode(seq_encoded)
6518 seq_encoded_expected = []
6519 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6520 if tag_num == dummy_seq_tag_num:
6521 seq_encoded_expected.append(seq["seq"].encode())
6523 seq_encoded_expected.append(seq[str(tag_num)].encode())
6524 self.assertSequenceEqual(
6525 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6526 b"".join(seq_encoded_expected),
6529 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6530 encoded += seq["seq"].encode()
6531 seq_encoded = b"".join((
6533 len_encode(len(encoded)),
6536 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6537 seq.decode(seq_encoded)
6538 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6539 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6540 self.assertTrue(seq_decoded.ber_encoded)
6541 self.assertTrue(seq_decoded.bered)
6542 seq_decoded = copy(seq_decoded)
6543 self.assertTrue(seq_decoded.ber_encoded)
6544 self.assertTrue(seq_decoded.bered)
6546 def test_same_value_twice(self):
6549 ("bool", Boolean()),
6553 encoded = b"".join((
6554 Integer(123).encode(),
6555 Integer(234).encode(),
6556 Boolean(True).encode(),
6558 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6559 with self.assertRaises(TagMismatch):
6560 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6564 def seqof_values_strategy(draw, schema=None, do_expl=False):
6566 schema = draw(sampled_from((Boolean(), Integer())))
6567 bound_min, bound_max = sorted(draw(sets(
6568 integers(min_value=0, max_value=10),
6572 if isinstance(schema, Boolean):
6573 values_generator = booleans().map(Boolean)
6574 elif isinstance(schema, Integer):
6575 values_generator = integers().map(Integer)
6576 values_generator = lists(
6581 values = draw(one_of(none(), values_generator))
6585 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6587 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6588 default = draw(one_of(none(), values_generator))
6589 optional = draw(one_of(none(), booleans()))
6591 draw(integers(min_value=0)),
6592 draw(integers(min_value=0)),
6593 draw(integers(min_value=0)),
6598 (bound_min, bound_max),
6607 class SeqOfMixing(object):
6608 def test_invalid_value_type(self):
6609 with self.assertRaises(InvalidValueType) as err:
6610 self.base_klass(123)
6613 def test_invalid_values_type(self):
6614 class SeqOf(self.base_klass):
6616 with self.assertRaises(InvalidValueType) as err:
6617 SeqOf([Integer(123), Boolean(False), Integer(234)])
6620 def test_schema_required(self):
6621 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6622 self.base_klass.__mro__[1]()
6624 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6625 def test_comparison(self, value1, value2, tag1, tag2):
6626 class SeqOf(self.base_klass):
6628 obj1 = SeqOf([Boolean(value1)])
6629 obj2 = SeqOf([Boolean(value2)])
6630 self.assertEqual(obj1 == obj2, value1 == value2)
6631 self.assertEqual(obj1 != obj2, value1 != value2)
6632 self.assertEqual(obj1 == list(obj2), value1 == value2)
6633 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6634 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6635 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6636 self.assertEqual(obj1 == obj2, tag1 == tag2)
6637 self.assertEqual(obj1 != obj2, tag1 != tag2)
6639 @given(lists(booleans()))
6640 def test_iter(self, values):
6641 class SeqOf(self.base_klass):
6643 obj = SeqOf([Boolean(value) for value in values])
6644 self.assertEqual(len(obj), len(values))
6645 for i, value in enumerate(obj):
6646 self.assertEqual(value, values[i])
6648 @given(data_strategy())
6649 def test_ready(self, d):
6650 ready = [Integer(v) for v in d.draw(lists(
6657 range(d.draw(integers(min_value=1, max_value=5)))
6660 class SeqOf(self.base_klass):
6662 values = d.draw(permutations(ready + non_ready))
6664 for value in values:
6666 self.assertFalse(seqof.ready)
6669 pprint(seqof, big_blobs=True, with_decode_path=True)
6670 with self.assertRaises(ObjNotReady) as err:
6673 with self.assertRaises(ObjNotReady) as err:
6675 for i, value in enumerate(values):
6676 self.assertEqual(seqof[i], value)
6677 if not seqof[i].ready:
6678 seqof[i] = Integer(i)
6679 self.assertTrue(seqof.ready)
6682 pprint(seqof, big_blobs=True, with_decode_path=True)
6684 def test_spec_mismatch(self):
6685 class SeqOf(self.base_klass):
6688 seqof.append(Integer(123))
6689 with self.assertRaises(ValueError):
6690 seqof.append(Boolean(False))
6691 with self.assertRaises(ValueError):
6692 seqof[0] = Boolean(False)
6694 @given(data_strategy())
6695 def test_bounds_satisfied(self, d):
6696 class SeqOf(self.base_klass):
6698 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6699 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6700 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6701 SeqOf(value=value, bounds=(bound_min, bound_max))
6703 @given(data_strategy())
6704 def test_bounds_unsatisfied(self, d):
6705 class SeqOf(self.base_klass):
6707 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6708 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6709 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6710 with self.assertRaises(BoundsError) as err:
6711 SeqOf(value=value, bounds=(bound_min, bound_max))
6713 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6714 SeqOf(bounds=(bound_min, bound_max)).decode(
6715 SeqOf(value).encode()
6718 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6719 SeqOf(bounds=(bound_min, bound_max)).decode(
6720 encode2pass(SeqOf(value))
6722 value = [Boolean(True)] * d.draw(integers(
6723 min_value=bound_max + 1,
6724 max_value=bound_max + 10,
6726 with self.assertRaises(BoundsError) as err:
6727 SeqOf(value=value, bounds=(bound_min, bound_max))
6729 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6730 SeqOf(bounds=(bound_min, bound_max)).decode(
6731 SeqOf(value).encode()
6734 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6735 SeqOf(bounds=(bound_min, bound_max)).decode(
6736 encode2pass(SeqOf(value))
6739 @given(integers(min_value=1, max_value=10))
6740 def test_out_of_bounds(self, bound_max):
6741 class SeqOf(self.base_klass):
6743 bounds = (0, bound_max)
6745 for _ in range(bound_max):
6746 seqof.append(Integer(123))
6747 with self.assertRaises(BoundsError):
6748 seqof.append(Integer(123))
6750 @given(data_strategy())
6751 def test_call(self, d):
6761 ) = d.draw(seqof_values_strategy())
6763 class SeqOf(self.base_klass):
6764 schema = schema_initial
6765 obj_initial = SeqOf(
6766 value=value_initial,
6767 bounds=bounds_initial,
6770 default=default_initial,
6771 optional=optional_initial or False,
6772 _decoded=_decoded_initial,
6783 ) = d.draw(seqof_values_strategy(
6784 schema=schema_initial,
6785 do_expl=impl_initial is None,
6787 if (default is None) and (obj_initial.default is not None):
6790 (bounds is None) and
6791 (value is not None) and
6792 (bounds_initial is not None) and
6793 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6797 (bounds is None) and
6798 (default is not None) and
6799 (bounds_initial is not None) and
6800 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6812 value_expected = default if value is None else value
6814 default_initial if value_expected is None
6817 value_expected = () if value_expected is None else value_expected
6818 self.assertEqual(obj, value_expected)
6819 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6820 self.assertEqual(obj.expl_tag, expl or expl_initial)
6823 default_initial if default is None else default,
6825 if obj.default is None:
6826 optional = optional_initial if optional is None else optional
6827 optional = False if optional is None else optional
6830 self.assertEqual(obj.optional, optional)
6832 (obj._bound_min, obj._bound_max),
6833 bounds or bounds_initial or (0, float("+inf")),
6836 @given(seqof_values_strategy())
6837 def test_copy(self, values):
6838 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6840 class SeqOf(self.base_klass):
6842 register_class(SeqOf)
6849 optional=optional or False,
6852 for copy_func in copy_funcs:
6853 obj_copied = copy_func(obj)
6854 self.assert_copied_basic_fields(obj, obj_copied)
6855 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6856 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6857 self.assertEqual(obj._value, obj_copied._value)
6861 integers(min_value=1).map(tag_encode),
6863 def test_stripped(self, values, tag_impl):
6864 class SeqOf(self.base_klass):
6865 schema = OctetString()
6866 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6867 with self.assertRaises(NotEnoughData):
6868 obj.decode(obj.encode()[:-1])
6872 integers(min_value=1).map(tag_ctxc),
6874 def test_stripped_expl(self, values, tag_expl):
6875 class SeqOf(self.base_klass):
6876 schema = OctetString()
6877 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6878 with self.assertRaises(NotEnoughData):
6879 obj.decode(obj.encode()[:-1])
6882 integers(min_value=31),
6883 integers(min_value=0),
6886 def test_bad_tag(self, tag, offset, decode_path):
6887 with self.assertRaises(DecodeError) as err:
6888 self.base_klass().decode(
6889 tag_encode(tag)[:-1],
6891 decode_path=decode_path,
6894 self.assertEqual(err.exception.offset, offset)
6895 self.assertEqual(err.exception.decode_path, decode_path)
6898 integers(min_value=128),
6899 integers(min_value=0),
6902 def test_bad_len(self, l, offset, decode_path):
6903 with self.assertRaises(DecodeError) as err:
6904 self.base_klass().decode(
6905 self.base_klass.tag_default + len_encode(l)[:-1],
6907 decode_path=decode_path,
6910 self.assertEqual(err.exception.offset, offset)
6911 self.assertEqual(err.exception.decode_path, decode_path)
6913 @given(binary(min_size=1))
6914 def test_tag_mismatch(self, impl):
6915 assume(impl != self.base_klass.tag_default)
6916 with self.assertRaises(TagMismatch):
6917 self.base_klass(impl=impl).decode(self.base_klass().encode())
6919 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6921 seqof_values_strategy(schema=Integer()),
6922 lists(integers().map(Integer)),
6923 integers(min_value=1).map(tag_ctxc),
6924 integers(min_value=0),
6928 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6929 _, _, _, _, _, default, optional, _decoded = values
6931 class SeqOf(self.base_klass):
6941 pprint(obj, big_blobs=True, with_decode_path=True)
6942 self.assertFalse(obj.expled)
6943 obj_encoded = obj.encode()
6944 self.assertEqual(encode2pass(obj), obj_encoded)
6945 obj_encoded_cer = encode_cer(obj)
6946 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6947 self.assertSequenceEqual(
6948 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6951 obj_expled = obj(value, expl=tag_expl)
6952 self.assertTrue(obj_expled.expled)
6954 list(obj_expled.pps())
6955 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6956 obj_expled_encoded = obj_expled.encode()
6957 ctx_copied = deepcopy(ctx_dummy)
6958 obj_decoded, tail = obj_expled.decode(
6959 obj_expled_encoded + tail_junk,
6963 self.assertDictEqual(ctx_copied, ctx_dummy)
6965 list(obj_decoded.pps())
6966 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6967 self.assertEqual(tail, tail_junk)
6968 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6969 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6970 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6971 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6973 obj_decoded.expl_llen,
6974 len(len_encode(len(obj_encoded))),
6976 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6977 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6980 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6982 self.assertEqual(obj_decoded.expl_offset, offset)
6983 for obj_inner in obj_decoded:
6984 self.assertIn(obj_inner, obj_decoded)
6985 self.assertSequenceEqual(
6988 obj_inner.offset - offset:
6989 obj_inner.offset + obj_inner.tlvlen - offset
6993 t, _, lv = tag_strip(obj_encoded)
6994 _, _, v = len_decode(lv)
6995 obj_encoded_lenindef = t + LENINDEF + v + EOC
6996 with self.assertRaises(DecodeError):
6997 obj.decode(obj_encoded_lenindef)
6998 obj_decoded_lenindef, tail_lenindef = obj.decode(
6999 obj_encoded_lenindef + tail_junk,
7000 ctx={"bered": True},
7002 self.assertTrue(obj_decoded_lenindef.lenindef)
7003 self.assertTrue(obj_decoded_lenindef.bered)
7004 obj_decoded_lenindef = copy(obj_decoded_lenindef)
7005 self.assertTrue(obj_decoded_lenindef.lenindef)
7006 self.assertTrue(obj_decoded_lenindef.bered)
7007 repr(obj_decoded_lenindef)
7008 list(obj_decoded_lenindef.pps())
7009 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
7010 self.assertEqual(tail_lenindef, tail_junk)
7011 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
7012 with self.assertRaises(DecodeError):
7013 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
7014 with self.assertRaises(DecodeError):
7015 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
7017 evgens = list(obj.decode_evgen(
7018 obj_encoded_lenindef + tail_junk,
7019 decode_path=decode_path,
7020 ctx={"bered": True},
7022 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
7023 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
7024 self.assertEqual(_decode_path, decode_path + (str(i),))
7027 _decode_path, obj, tail = evgens[-1]
7028 self.assertEqual(_decode_path, decode_path)
7032 assert_exceeding_data(
7034 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
7038 def test_bered(self):
7039 class SeqOf(self.base_klass):
7041 encoded = Boolean(False).encode()
7042 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
7043 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7044 with self.assertRaises(DecodeError):
7045 SeqOf().decode(encoded)
7046 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7047 self.assertFalse(decoded.ber_encoded)
7048 self.assertFalse(decoded.lenindef)
7049 self.assertTrue(decoded.bered)
7050 decoded = copy(decoded)
7051 self.assertFalse(decoded.ber_encoded)
7052 self.assertFalse(decoded.lenindef)
7053 self.assertTrue(decoded.bered)
7055 class SeqOf(self.base_klass):
7056 schema = OctetString()
7057 encoded = OctetString(b"whatever").encode()
7059 tag_encode(form=TagFormConstructed, num=4) +
7061 OctetString(b"whatever").encode() +
7064 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7065 with self.assertRaises(DecodeError):
7066 SeqOf().decode(encoded)
7067 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7068 self.assertFalse(decoded.ber_encoded)
7069 self.assertFalse(decoded.lenindef)
7070 self.assertTrue(decoded.bered)
7071 decoded = copy(decoded)
7072 self.assertFalse(decoded.ber_encoded)
7073 self.assertFalse(decoded.lenindef)
7074 self.assertTrue(decoded.bered)
7077 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7078 class SeqOf(SequenceOf):
7082 def _test_symmetric_compare_objs(self, obj1, obj2):
7083 self.assertEqual(obj1, obj2)
7084 self.assertSequenceEqual(list(obj1), list(obj2))
7086 def test_iterator_pickling(self):
7087 class SeqOf(SequenceOf):
7089 register_class(SeqOf)
7092 seqof = seqof(iter(six_xrange(10)))
7093 with assertRaisesRegex(self, ValueError, "iterator"):
7096 def test_iterator_bounds(self):
7097 class SeqOf(SequenceOf):
7103 for i in six_xrange(n):
7106 seqof = SeqOf(gen(n))
7107 self.assertTrue(seqof.ready)
7108 with self.assertRaises(BoundsError):
7110 self.assertFalse(seqof.ready)
7111 seqof = seqof(gen(n))
7112 self.assertTrue(seqof.ready)
7113 with self.assertRaises(BoundsError):
7115 self.assertFalse(seqof.ready)
7117 def test_iterator_twice(self):
7118 class SeqOf(SequenceOf):
7120 bounds = (1, float("+inf"))
7123 for i in six_xrange(10):
7125 seqof = SeqOf(gen())
7126 self.assertTrue(seqof.ready)
7128 self.assertFalse(seqof.ready)
7129 register_class(SeqOf)
7132 def test_iterator_2pass(self):
7133 class SeqOf(SequenceOf):
7135 bounds = (1, float("+inf"))
7138 for i in six_xrange(10):
7140 seqof = SeqOf(gen())
7141 self.assertTrue(seqof.ready)
7142 _, state = seqof.encode1st()
7143 self.assertFalse(seqof.ready)
7144 seqof = seqof(gen())
7145 self.assertTrue(seqof.ready)
7147 seqof.encode2nd(buf.write, iter(state))
7148 self.assertSequenceEqual(
7149 [int(i) for i in seqof.decod(buf.getvalue())],
7153 def test_non_ready_bound_min(self):
7154 class SeqOf(SequenceOf):
7156 bounds = (1, float("+inf"))
7158 self.assertFalse(seqof.ready)
7161 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7166 def _test_symmetric_compare_objs(self, obj1, obj2):
7167 self.assertSetEqual(
7168 set(int(v) for v in obj1),
7169 set(int(v) for v in obj2),
7172 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7173 @given(data_strategy())
7174 def test_sorted(self, d):
7175 values = [OctetString(v) for v in d.draw(lists(binary()))]
7178 schema = OctetString()
7180 seq_encoded = seq.encode()
7181 seq_decoded, _ = seq.decode(seq_encoded)
7182 self.assertSequenceEqual(
7183 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7184 b"".join(sorted([v.encode() for v in values])),
7187 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7188 @given(data_strategy())
7189 def test_unsorted(self, d):
7190 values = [OctetString(v).encode() for v in d.draw(sets(
7191 binary(min_size=1, max_size=5),
7195 values = d.draw(permutations(values))
7196 assume(values != sorted(values))
7197 encoded = b"".join(values)
7198 seq_encoded = b"".join((
7200 len_encode(len(encoded)),
7205 schema = OctetString()
7207 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7208 seq.decode(seq_encoded)
7210 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7211 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7212 self.assertTrue(seq_decoded.ber_encoded)
7213 self.assertTrue(seq_decoded.bered)
7214 seq_decoded = copy(seq_decoded)
7215 self.assertTrue(seq_decoded.ber_encoded)
7216 self.assertTrue(seq_decoded.bered)
7217 self.assertSequenceEqual(
7218 [obj.encode() for obj in seq_decoded],
7223 class TestGoMarshalVectors(TestCase):
7225 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7226 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7227 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7228 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7229 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7231 class Seq(Sequence):
7233 ("erste", Integer()),
7234 ("zweite", Integer(optional=True))
7237 seq["erste"] = Integer(64)
7238 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7239 seq["erste"] = Integer(0x123456)
7240 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7241 seq["erste"] = Integer(64)
7242 seq["zweite"] = Integer(65)
7243 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7245 class NestedSeq(Sequence):
7249 seq["erste"] = Integer(127)
7250 seq["zweite"] = None
7251 nested = NestedSeq()
7252 nested["nest"] = seq
7253 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7255 self.assertSequenceEqual(
7256 OctetString(b"\x01\x02\x03").encode(),
7257 hexdec("0403010203"),
7260 class Seq(Sequence):
7262 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7265 seq["erste"] = Integer(64)
7266 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7268 class Seq(Sequence):
7270 ("erste", Integer(expl=tag_ctxc(5))),
7273 seq["erste"] = Integer(64)
7274 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7276 class Seq(Sequence):
7279 impl=tag_encode(0, klass=TagClassContext),
7284 seq["erste"] = Null()
7285 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7287 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7289 self.assertSequenceEqual(
7290 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7291 hexdec("170d3730303130313030303030305a"),
7293 self.assertSequenceEqual(
7294 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7295 hexdec("170d3039313131353232353631365a"),
7297 self.assertSequenceEqual(
7298 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7299 hexdec("180f32313030303430353132303130315a"),
7302 class Seq(Sequence):
7304 ("erste", GeneralizedTime()),
7307 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7308 self.assertSequenceEqual(
7310 hexdec("3011180f32303039313131353232353631365a"),
7313 self.assertSequenceEqual(
7314 BitString((1, b"\x80")).encode(),
7317 self.assertSequenceEqual(
7318 BitString((12, b"\x81\xF0")).encode(),
7319 hexdec("03030481f0"),
7322 self.assertSequenceEqual(
7323 ObjectIdentifier("1.2.3.4").encode(),
7324 hexdec("06032a0304"),
7326 self.assertSequenceEqual(
7327 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7328 hexdec("06092a864888932d010105"),
7330 self.assertSequenceEqual(
7331 ObjectIdentifier("2.100.3").encode(),
7332 hexdec("0603813403"),
7335 self.assertSequenceEqual(
7336 PrintableString("test").encode(),
7337 hexdec("130474657374"),
7339 self.assertSequenceEqual(
7340 PrintableString("x" * 127).encode(),
7341 hexdec("137F" + "78" * 127),
7343 self.assertSequenceEqual(
7344 PrintableString("x" * 128).encode(),
7345 hexdec("138180" + "78" * 128),
7347 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7349 class Seq(Sequence):
7351 ("erste", IA5String()),
7354 seq["erste"] = IA5String("test")
7355 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7357 class Seq(Sequence):
7359 ("erste", PrintableString()),
7362 seq["erste"] = PrintableString("test")
7363 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7364 # Asterisk is actually not allowable
7365 PrintableString._allowable_chars |= set(b"*")
7366 seq["erste"] = PrintableString("test*")
7367 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7368 PrintableString._allowable_chars -= set(b"*")
7370 class Seq(Sequence):
7372 ("erste", Any(optional=True)),
7373 ("zweite", Integer()),
7376 seq["zweite"] = Integer(64)
7377 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7382 seq.append(Integer(10))
7383 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7385 class _SeqOf(SequenceOf):
7386 schema = PrintableString()
7388 class SeqOf(SequenceOf):
7391 _seqof.append(PrintableString("1"))
7393 seqof.append(_seqof)
7394 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7396 class Seq(Sequence):
7398 ("erste", Integer(default=1)),
7401 seq["erste"] = Integer(0)
7402 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7403 seq["erste"] = Integer(1)
7404 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7405 seq["erste"] = Integer(2)
7406 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7409 class TestPP(TestCase):
7410 @given(data_strategy())
7411 def test_oid_printing(self, d):
7413 str(ObjectIdentifier(k)): v * 2
7414 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7416 chosen = d.draw(sampled_from(sorted(oids)))
7417 chosen_id = oids[chosen]
7418 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7419 self.assertNotIn(chosen_id, pp_console_row(pp))
7422 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7426 class TestAutoAddSlots(TestCase):
7428 class Inher(Integer):
7431 with self.assertRaises(AttributeError):
7433 inher.unexistent = "whatever"
7436 class TestOIDDefines(TestCase):
7437 @given(data_strategy())
7438 def runTest(self, d):
7439 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7440 value_name_chosen = d.draw(sampled_from(value_names))
7442 ObjectIdentifier(oid)
7443 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7445 oid_chosen = d.draw(sampled_from(oids))
7446 values = d.draw(lists(
7448 min_size=len(value_names),
7449 max_size=len(value_names),
7451 for definable_class in (Any, OctetString, BitString):
7453 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7454 oid: Integer() for oid in oids[:-1]
7457 for i, value_name in enumerate(value_names):
7458 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7460 class Seq(Sequence):
7463 for value_name, value in zip(value_names, values):
7464 seq[value_name] = definable_class(Integer(value).encode())
7465 seq["type"] = oid_chosen
7466 seq, _ = Seq().decode(seq.encode())
7467 for value_name in value_names:
7468 if value_name == value_name_chosen:
7470 self.assertIsNone(seq[value_name].defined)
7471 if value_name_chosen in oids[:-1]:
7472 self.assertIsNotNone(seq[value_name_chosen].defined)
7473 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7474 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7477 pprint(seq, big_blobs=True, with_decode_path=True)
7480 class TestDefinesByPath(TestCase):
7481 def test_generated(self):
7482 class Seq(Sequence):
7484 ("type", ObjectIdentifier()),
7485 ("value", OctetString(expl=tag_ctxc(123))),
7488 class SeqInner(Sequence):
7490 ("typeInner", ObjectIdentifier()),
7491 ("valueInner", Any()),
7494 class PairValue(SetOf):
7497 class Pair(Sequence):
7499 ("type", ObjectIdentifier()),
7500 ("value", PairValue()),
7503 class Pairs(SequenceOf):
7510 type_octet_stringed,
7512 ObjectIdentifier(oid)
7513 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7515 seq_integered = Seq()
7516 seq_integered["type"] = type_integered
7517 seq_integered["value"] = OctetString(Integer(123).encode())
7518 seq_integered_raw = seq_integered.encode()
7522 (type_octet_stringed, OctetString(b"whatever")),
7523 (type_integered, Integer(123)),
7524 (type_octet_stringed, OctetString(b"whenever")),
7525 (type_integered, Integer(234)),
7527 for t, v in pairs_input:
7530 ("value", PairValue((Any(v),))),
7532 seq_inner = SeqInner()
7533 seq_inner["typeInner"] = type_innered
7534 seq_inner["valueInner"] = Any(pairs)
7535 seq_sequenced = Seq()
7536 seq_sequenced["type"] = type_sequenced
7537 seq_sequenced["value"] = OctetString(seq_inner.encode())
7538 seq_sequenced_raw = seq_sequenced.encode()
7540 list(seq_sequenced.pps())
7541 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7543 defines_by_path = []
7544 ctx_copied = deepcopy(ctx_dummy)
7545 seq_integered, _ = Seq().decode(
7549 self.assertDictEqual(ctx_copied, ctx_dummy)
7550 self.assertIsNone(seq_integered["value"].defined)
7551 defines_by_path.append(
7552 (("type",), ((("value",), {
7553 type_integered: Integer(),
7554 type_sequenced: SeqInner(),
7557 ctx_copied["defines_by_path"] = defines_by_path
7558 seq_integered, _ = Seq().decode(
7562 del ctx_copied["defines_by_path"]
7563 self.assertDictEqual(ctx_copied, ctx_dummy)
7564 self.assertIsNotNone(seq_integered["value"].defined)
7565 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7566 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7567 self.assertTrue(seq_integered_raw[
7568 seq_integered["value"].defined[1].offset:
7569 ].startswith(Integer(123).encode()))
7571 list(seq_integered.pps())
7572 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7574 ctx_copied["defines_by_path"] = defines_by_path
7575 seq_sequenced, _ = Seq().decode(
7579 del ctx_copied["defines_by_path"]
7580 self.assertDictEqual(ctx_copied, ctx_dummy)
7581 self.assertIsNotNone(seq_sequenced["value"].defined)
7582 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7583 seq_inner = seq_sequenced["value"].defined[1]
7584 self.assertIsNone(seq_inner["valueInner"].defined)
7586 list(seq_sequenced.pps())
7587 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7589 defines_by_path.append((
7590 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7591 ((("valueInner",), {type_innered: Pairs()}),),
7593 ctx_copied["defines_by_path"] = defines_by_path
7594 seq_sequenced, _ = Seq().decode(
7598 del ctx_copied["defines_by_path"]
7599 self.assertDictEqual(ctx_copied, ctx_dummy)
7600 self.assertIsNotNone(seq_sequenced["value"].defined)
7601 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7602 seq_inner = seq_sequenced["value"].defined[1]
7603 self.assertIsNotNone(seq_inner["valueInner"].defined)
7604 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7605 pairs = seq_inner["valueInner"].defined[1]
7607 self.assertIsNone(pair["value"][0].defined)
7609 list(seq_sequenced.pps())
7610 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7612 defines_by_path.append((
7615 DecodePathDefBy(type_sequenced),
7617 DecodePathDefBy(type_innered),
7622 type_integered: Integer(),
7623 type_octet_stringed: OctetString(),
7626 ctx_copied["defines_by_path"] = defines_by_path
7627 seq_sequenced, _ = Seq().decode(
7631 del ctx_copied["defines_by_path"]
7632 self.assertDictEqual(ctx_copied, ctx_dummy)
7633 self.assertIsNotNone(seq_sequenced["value"].defined)
7634 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7635 seq_inner = seq_sequenced["value"].defined[1]
7636 self.assertIsNotNone(seq_inner["valueInner"].defined)
7637 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7638 pairs_got = seq_inner["valueInner"].defined[1]
7639 for pair_input, pair_got in zip(pairs_input, pairs_got):
7640 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7641 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7643 list(seq_sequenced.pps())
7644 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7646 @given(oid_strategy(), integers())
7647 def test_simple(self, oid, tgt):
7648 class Inner(Sequence):
7650 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7651 ObjectIdentifier(oid): Integer(),
7655 class Outer(Sequence):
7658 ("tgt", OctetString()),
7662 inner["oid"] = ObjectIdentifier(oid)
7664 outer["inner"] = inner
7665 outer["tgt"] = OctetString(Integer(tgt).encode())
7666 decoded, _ = Outer().decode(outer.encode())
7667 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7669 def test_remaining_data(self):
7670 oid = ObjectIdentifier("1.2.3")
7672 class Seq(Sequence):
7674 ("oid", ObjectIdentifier(defines=((("tgt",), {
7677 ("tgt", OctetString()),
7682 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7684 with assertRaisesRegex(self, DecodeError, "remaining data"):
7685 Seq().decode(seq.encode())
7687 def test_remaining_data_seqof(self):
7688 oid = ObjectIdentifier("1.2.3")
7691 schema = OctetString()
7693 class Seq(Sequence):
7695 ("oid", ObjectIdentifier(defines=((("tgt",), {
7703 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7705 with assertRaisesRegex(self, DecodeError, "remaining data"):
7706 Seq().decode(seq.encode())
7709 class TestAbsDecodePath(TestCase):
7711 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7712 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7714 def test_concat(self, decode_path, rel_path):
7715 dp = abs_decode_path(decode_path, rel_path)
7716 self.assertSequenceEqual(dp, decode_path + rel_path)
7720 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7721 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7723 def test_abs(self, decode_path, rel_path):
7724 self.assertSequenceEqual(
7725 abs_decode_path(decode_path, ("/",) + rel_path),
7730 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7731 integers(min_value=1, max_value=3),
7732 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7734 def test_dots(self, decode_path, number_of_dots, rel_path):
7735 self.assertSequenceEqual(
7736 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7737 decode_path[:-number_of_dots] + rel_path,
7741 class TestStrictDefaultExistence(TestCase):
7742 @given(data_strategy())
7743 def runTest(self, d):
7744 count = d.draw(integers(min_value=1, max_value=10))
7745 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7747 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7748 for i in range(count)
7750 for klass in (Sequence, Set):
7754 for i in range(count):
7755 seq["int%d" % i] = Integer(123)
7757 chosen_choice = "int%d" % chosen
7758 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7759 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7761 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7762 self.assertTrue(decoded.ber_encoded)
7763 self.assertTrue(decoded.bered)
7764 decoded = copy(decoded)
7765 self.assertTrue(decoded.ber_encoded)
7766 self.assertTrue(decoded.bered)
7767 decoded, _ = seq.decode(raw, ctx={"bered": True})
7768 self.assertTrue(decoded.ber_encoded)
7769 self.assertTrue(decoded.bered)
7770 decoded = copy(decoded)
7771 self.assertTrue(decoded.ber_encoded)
7772 self.assertTrue(decoded.bered)
7775 class TestX690PrefixedType(TestCase):
7777 self.assertSequenceEqual(
7778 VisibleString("Jones").encode(),
7779 hexdec("1A054A6F6E6573"),
7783 self.assertSequenceEqual(
7786 impl=tag_encode(3, klass=TagClassApplication),
7788 hexdec("43054A6F6E6573"),
7792 self.assertSequenceEqual(
7796 impl=tag_encode(3, klass=TagClassApplication),
7800 hexdec("A20743054A6F6E6573"),
7804 self.assertSequenceEqual(
7808 impl=tag_encode(3, klass=TagClassApplication),
7810 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7812 hexdec("670743054A6F6E6573"),
7816 self.assertSequenceEqual(
7817 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7818 hexdec("82054A6F6E6573"),
7822 class TestExplOOB(TestCase):
7824 expl = tag_ctxc(123)
7825 raw = Integer(123).encode() + Integer(234).encode()
7826 raw = b"".join((expl, len_encode(len(raw)), raw))
7827 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7828 Integer(expl=expl).decode(raw)
7829 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7832 class TestPickleDifferentVersion(TestCase):
7834 pickled = pickle_dumps(Integer(123), pickle_proto)
7836 version_orig = pyderasn.__version__
7837 pyderasn.__version__ += "different"
7838 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7839 pickle_loads(pickled)
7840 pyderasn.__version__ = version_orig
7841 pickle_loads(pickled)
7844 class TestCERSetOrdering(TestCase):
7845 def test_vectors(self):
7846 """Taken from X.690-201508
7850 ("c", Integer(impl=tag_ctxp(2))),
7851 ("d", Integer(impl=tag_ctxp(4))),
7856 ("g", Integer(impl=tag_ctxp(5))),
7857 ("h", Integer(impl=tag_ctxp(6))),
7862 ("j", Integer(impl=tag_ctxp(0))),
7873 ("a", Integer(impl=tag_ctxp(3))),
7874 ("b", B(expl=tag_ctxc(1))),
7879 ("a", Integer(123)),
7880 ("b", B(("d", Integer(234)))),
7881 ("e", E(("f", F(("g", Integer(345)))))),
7883 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7884 self.assertSequenceEqual(
7885 [i.__class__.__name__ for i in order],
7886 ("E", "B", "Integer"),