2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2021 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 dateutil.tz import UTC
37 from hypothesis import assume
38 from hypothesis import given
39 from hypothesis import settings
40 from hypothesis.strategies import binary
41 from hypothesis.strategies import booleans
42 from hypothesis.strategies import composite
43 from hypothesis.strategies import data as data_strategy
44 from hypothesis.strategies import datetimes
45 from hypothesis.strategies import dictionaries
46 from hypothesis.strategies import integers
47 from hypothesis.strategies import just
48 from hypothesis.strategies import lists
49 from hypothesis.strategies import none
50 from hypothesis.strategies import one_of
51 from hypothesis.strategies import permutations
52 from hypothesis.strategies import sampled_from
53 from hypothesis.strategies import sets
54 from hypothesis.strategies import text
55 from hypothesis.strategies import tuples
56 from six import assertRaisesRegex
57 from six import binary_type
58 from six import byte2int
59 from six import indexbytes
60 from six import int2byte
61 from six import iterbytes
63 from six import text_type
64 from six import unichr as six_unichr
65 from six.moves import xrange as six_xrange
66 from six.moves.cPickle import dumps as pickle_dumps
67 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
68 from six.moves.cPickle import loads as pickle_loads
70 from pyderasn import _pp
71 from pyderasn import abs_decode_path
72 from pyderasn import Any
73 from pyderasn import BitString
74 from pyderasn import BMPString
75 from pyderasn import Boolean
76 from pyderasn import BoundsError
77 from pyderasn import Choice
78 from pyderasn import DecodeError
79 from pyderasn import DecodePathDefBy
80 from pyderasn import encode2pass
81 from pyderasn import encode_cer
82 from pyderasn import Enumerated
83 from pyderasn import EOC
84 from pyderasn import EOC_LEN
85 from pyderasn import ExceedingData
86 from pyderasn import GeneralizedTime
87 from pyderasn import GeneralString
88 from pyderasn import GraphicString
89 from pyderasn import hexdec
90 from pyderasn import hexenc
91 from pyderasn import IA5String
92 from pyderasn import Integer
93 from pyderasn import InvalidLength
94 from pyderasn import InvalidOID
95 from pyderasn import InvalidValueType
96 from pyderasn import len_decode
97 from pyderasn import len_encode
98 from pyderasn import LEN_YYMMDDHHMMSSZ
99 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
100 from pyderasn import LEN_YYYYMMDDHHMMSSZ
101 from pyderasn import LENINDEF
102 from pyderasn import LenIndefForm
103 from pyderasn import NotEnoughData
104 from pyderasn import Null
105 from pyderasn import NumericString
106 from pyderasn import ObjectIdentifier
107 from pyderasn import ObjNotReady
108 from pyderasn import ObjUnknown
109 from pyderasn import OctetString
110 from pyderasn import pp_console_row
111 from pyderasn import pprint
112 from pyderasn import PrintableString
113 from pyderasn import Sequence
114 from pyderasn import SequenceOf
115 from pyderasn import Set
116 from pyderasn import SetOf
117 from pyderasn import tag_ctxc
118 from pyderasn import tag_ctxp
119 from pyderasn import tag_decode
120 from pyderasn import tag_encode
121 from pyderasn import tag_strip
122 from pyderasn import TagClassApplication
123 from pyderasn import TagClassContext
124 from pyderasn import TagClassPrivate
125 from pyderasn import TagClassUniversal
126 from pyderasn import TagFormConstructed
127 from pyderasn import TagFormPrimitive
128 from pyderasn import TagMismatch
129 from pyderasn import TeletexString
130 from pyderasn import UniversalString
131 from pyderasn import UTCTime
132 from pyderasn import UTF8String
133 from pyderasn import VideotexString
134 from pyderasn import VisibleString
137 max_examples = environ.get("MAX_EXAMPLES")
138 settings.register_profile("local", settings(
140 **({"max_examples": int(max_examples)} if max_examples else {})
142 settings.load_profile("local")
143 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
145 tag_classes = sampled_from((
151 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
152 decode_path_strat = lists(integers(), max_size=3).map(
153 lambda decode_path: tuple(str(dp) for dp in decode_path)
155 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
158 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
160 self_module = import_module(__name__)
163 def register_class(klass):
164 klassname = klass.__name__ + str(time()).replace(".", "")
165 klass.__name__ = klassname
166 klass.__qualname__ = klassname
167 setattr(self_module, klassname, klass)
170 def assert_exceeding_data(self, call, junk):
173 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
178 class TestHex(TestCase):
180 def test_symmetric(self, data):
181 self.assertEqual(hexdec(hexenc(data)), data)
184 class TestTagCoder(TestCase):
185 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
189 integers(min_value=0, max_value=30),
192 def test_short(self, klass, form, num, junk):
193 raw = tag_encode(klass=klass, form=form, num=num)
194 self.assertEqual(tag_decode(raw), (klass, form, num))
195 self.assertEqual(len(raw), 1)
197 byte2int(tag_encode(klass=klass, form=form, num=0)),
198 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
200 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
201 self.assertSequenceEqual(stripped.tobytes(), raw)
202 self.assertEqual(tlen, len(raw))
203 self.assertSequenceEqual(tail, junk)
205 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
209 integers(min_value=31),
212 def test_long(self, klass, form, num, junk):
213 raw = tag_encode(klass=klass, form=form, num=num)
214 self.assertEqual(tag_decode(raw), (klass, form, num))
215 self.assertGreater(len(raw), 1)
217 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
220 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
221 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
222 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
223 self.assertSequenceEqual(stripped.tobytes(), raw)
224 self.assertEqual(tlen, len(raw))
225 self.assertSequenceEqual(tail, junk)
227 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
228 @given(integers(min_value=31))
229 def test_unfinished_tag(self, num):
230 raw = bytearray(tag_encode(num=num))
231 for i in range(1, len(raw)):
233 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
234 tag_strip(bytes(raw))
236 def test_go_vectors_valid(self):
237 for data, (eklass, etag, elen, eform) in (
238 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
239 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
240 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
241 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
242 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
243 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
244 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
245 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
246 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
247 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
249 tag, _, len_encoded = tag_strip(memoryview(data))
250 klass, form, num = tag_decode(tag)
251 _len, _, tail = len_decode(len_encoded)
252 self.assertSequenceEqual(tail, b"")
253 self.assertEqual(klass, eklass)
254 self.assertEqual(num, etag)
255 self.assertEqual(_len, elen)
256 self.assertEqual(form, eform)
258 def test_go_vectors_invalid(self):
266 with self.assertRaises(DecodeError):
267 _, _, len_encoded = tag_strip(memoryview(data))
268 len_decode(len_encoded)
271 integers(min_value=0, max_value=127),
272 integers(min_value=0, max_value=2),
274 def test_long_instead_of_short(self, l, dummy_num):
275 octets = (b"\x00" * dummy_num) + int2byte(l)
276 octets = int2byte((dummy_num + 1) | 0x80) + octets
277 with self.assertRaises(DecodeError):
280 @given(tag_classes, tag_forms, integers(min_value=31))
281 def test_leading_zero_byte(self, klass, form, num):
282 raw = tag_encode(klass=klass, form=form, num=num)
283 raw = b"".join((raw[:1], b"\x80", raw[1:]))
284 with assertRaisesRegex(self, DecodeError, "leading zero byte"):
287 @given(tag_classes, tag_forms, integers(max_value=30, min_value=0))
288 def test_unexpected_long_form(self, klass, form, num):
289 raw = int2byte(klass | form | 31) + int2byte(num)
290 with assertRaisesRegex(self, DecodeError, "unexpected long form"):
294 class TestLenCoder(TestCase):
295 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
297 integers(min_value=0, max_value=127),
300 def test_short(self, l, junk):
301 raw = len_encode(l) + junk
302 decoded, llen, tail = len_decode(memoryview(raw))
303 self.assertEqual(decoded, l)
304 self.assertEqual(llen, 1)
305 self.assertEqual(len(raw), 1 + len(junk))
306 self.assertEqual(tail.tobytes(), junk)
308 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
310 integers(min_value=128),
313 def test_long(self, l, junk):
314 raw = len_encode(l) + junk
315 decoded, llen, tail = len_decode(memoryview(raw))
316 self.assertEqual(decoded, l)
317 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
318 self.assertEqual(llen, len(raw) - len(junk))
319 self.assertNotEqual(indexbytes(raw, 1), 0)
320 self.assertSequenceEqual(tail.tobytes(), junk)
322 def test_empty(self):
323 with self.assertRaises(NotEnoughData):
326 @given(integers(min_value=128))
327 def test_stripped(self, _len):
328 with self.assertRaises(NotEnoughData):
329 len_decode(len_encode(_len)[:-1])
332 text_printable = text(alphabet=printable, min_size=1)
336 def text_letters(draw):
337 result = draw(text(alphabet=ascii_letters, min_size=1))
339 result = result.encode("ascii")
343 class CommonMixin(object):
344 def test_tag_default(self):
345 obj = self.base_klass()
346 self.assertEqual(obj.tag, obj.tag_default)
348 def test_simultaneous_impl_expl(self):
349 with self.assertRaises(ValueError):
350 self.base_klass(impl=b"whatever", expl=b"whenever")
352 @given(binary(min_size=1), integers(), integers(), integers())
353 def test_decoded(self, impl, offset, llen, vlen):
354 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
355 self.assertEqual(obj.offset, offset)
356 self.assertEqual(obj.llen, llen)
357 self.assertEqual(obj.vlen, vlen)
358 self.assertEqual(obj.tlen, len(impl))
359 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
361 @given(binary(min_size=1))
362 def test_impl_inherited(self, impl_tag):
363 class Inherited(self.base_klass):
366 self.assertSequenceEqual(obj.impl, impl_tag)
367 self.assertFalse(obj.expled)
369 tag_class, _, tag_num = tag_decode(impl_tag)
370 self.assertEqual(obj.tag_order, (tag_class, tag_num))
372 @given(binary(min_size=1))
373 def test_expl_inherited(self, expl_tag):
374 class Inherited(self.base_klass):
377 self.assertSequenceEqual(obj.expl, expl_tag)
378 self.assertTrue(obj.expled)
380 tag_class, _, tag_num = tag_decode(expl_tag)
381 self.assertEqual(obj.tag_order, (tag_class, tag_num))
383 def assert_copied_basic_fields(self, obj, obj_copied):
384 self.assertEqual(obj, obj_copied)
385 self.assertSequenceEqual(obj.tag, obj_copied.tag)
386 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
387 self.assertEqual(obj.default, obj_copied.default)
388 self.assertEqual(obj.optional, obj_copied.optional)
389 self.assertEqual(obj.offset, obj_copied.offset)
390 self.assertEqual(obj.llen, obj_copied.llen)
391 self.assertEqual(obj.vlen, obj_copied.vlen)
393 self.assertEqual(obj.tag_order, obj_copied.tag_order)
397 def boolean_values_strategy(draw, do_expl=False):
398 value = draw(one_of(none(), booleans()))
402 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
404 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
405 default = draw(one_of(none(), booleans()))
406 optional = draw(one_of(none(), booleans()))
408 draw(integers(min_value=0)),
409 draw(integers(min_value=0)),
410 draw(integers(min_value=0)),
412 return (value, impl, expl, default, optional, _decoded)
415 class BooleanInherited(Boolean):
419 class TestBoolean(CommonMixin, TestCase):
422 def test_invalid_value_type(self):
423 with self.assertRaises(InvalidValueType) as err:
428 def test_optional(self, optional):
429 obj = Boolean(default=Boolean(False), optional=optional)
430 self.assertTrue(obj.optional)
433 def test_ready(self, value):
435 self.assertFalse(obj.ready)
438 pprint(obj, big_blobs=True, with_decode_path=True)
439 with self.assertRaises(ObjNotReady) as err:
441 with self.assertRaises(ObjNotReady) as err:
445 self.assertTrue(obj.ready)
448 pprint(obj, big_blobs=True, with_decode_path=True)
450 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
451 def test_comparison(self, value1, value2, tag1, tag2):
452 for klass in (Boolean, BooleanInherited):
455 self.assertEqual(obj1 == obj2, value1 == value2)
456 self.assertEqual(obj1 != obj2, value1 != value2)
457 self.assertEqual(obj1 == bool(obj2), value1 == value2)
458 obj1 = klass(value1, impl=tag1)
459 obj2 = klass(value1, impl=tag2)
460 self.assertEqual(obj1 == obj2, tag1 == tag2)
461 self.assertEqual(obj1 != obj2, tag1 != tag2)
463 @given(data_strategy())
464 def test_call(self, d):
465 for klass in (Boolean, BooleanInherited):
473 ) = d.draw(boolean_values_strategy())
479 optional_initial or False,
489 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
490 obj = obj_initial(value, impl, expl, default, optional)
492 value_expected = default if value is None else value
494 default_initial if value_expected is None
497 self.assertEqual(obj, value_expected)
498 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
499 self.assertEqual(obj.expl_tag, expl or expl_initial)
502 default_initial if default is None else default,
504 if obj.default is None:
505 optional = optional_initial if optional is None else optional
506 optional = False if optional is None else optional
509 self.assertEqual(obj.optional, optional)
511 @given(boolean_values_strategy())
512 def test_copy(self, values):
513 for klass in (Boolean, BooleanInherited):
515 for copy_func in copy_funcs:
516 obj_copied = copy_func(obj)
517 self.assert_copied_basic_fields(obj, obj_copied)
521 integers(min_value=1).map(tag_encode),
523 def test_stripped(self, value, tag_impl):
524 obj = Boolean(value, impl=tag_impl)
525 with self.assertRaises(NotEnoughData):
526 obj.decode(obj.encode()[:-1])
527 with self.assertRaises(NotEnoughData):
528 obj.decode(encode2pass(obj)[:-1])
532 integers(min_value=1).map(tag_ctxc),
534 def test_stripped_expl(self, value, tag_expl):
535 obj = Boolean(value, expl=tag_expl)
536 with self.assertRaises(NotEnoughData):
537 obj.decode(obj.encode()[:-1])
538 with self.assertRaises(NotEnoughData):
539 obj.decode(encode2pass(obj)[:-1])
542 integers(min_value=31),
543 integers(min_value=0),
546 def test_bad_tag(self, tag, offset, decode_path):
547 with self.assertRaises(DecodeError) as err:
549 tag_encode(tag)[:-1],
551 decode_path=decode_path,
554 self.assertEqual(err.exception.offset, offset)
555 self.assertEqual(err.exception.decode_path, decode_path)
558 integers(min_value=31),
559 integers(min_value=0),
562 def test_bad_expl_tag(self, tag, offset, decode_path):
563 with self.assertRaises(DecodeError) as err:
564 Boolean(expl=Boolean.tag_default).decode(
565 tag_encode(tag)[:-1],
567 decode_path=decode_path,
570 self.assertEqual(err.exception.offset, offset)
571 self.assertEqual(err.exception.decode_path, decode_path)
574 integers(min_value=128),
575 integers(min_value=0),
578 def test_bad_len(self, l, offset, decode_path):
579 with self.assertRaises(DecodeError) as err:
581 Boolean.tag_default + len_encode(l)[:-1],
583 decode_path=decode_path,
586 self.assertEqual(err.exception.offset, offset)
587 self.assertEqual(err.exception.decode_path, decode_path)
590 integers(min_value=128),
591 integers(min_value=0),
594 def test_bad_expl_len(self, l, offset, decode_path):
595 with self.assertRaises(DecodeError) as err:
596 Boolean(expl=Boolean.tag_default).decode(
597 Boolean.tag_default + len_encode(l)[:-1],
599 decode_path=decode_path,
602 self.assertEqual(err.exception.offset, offset)
603 self.assertEqual(err.exception.decode_path, decode_path)
605 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
607 boolean_values_strategy(),
609 integers(min_value=1).map(tag_ctxc),
610 integers(min_value=0),
614 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
615 for klass in (Boolean, BooleanInherited):
616 _, _, _, default, optional, _decoded = values
625 pprint(obj, big_blobs=True, with_decode_path=True)
626 self.assertFalse(obj.expled)
627 obj_encoded = obj.encode()
628 self.assertEqual(encode2pass(obj), obj_encoded)
629 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
630 obj_expled = obj(value, expl=tag_expl)
631 self.assertTrue(obj_expled.expled)
633 list(obj_expled.pps())
634 pprint(obj_expled, big_blobs=True, with_decode_path=True)
635 obj_expled_cer = encode_cer(obj_expled)
636 self.assertNotEqual(obj_expled_cer, obj_encoded)
637 self.assertSequenceEqual(
638 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
641 obj_expled_hex_encoded = obj_expled.hexencode()
642 ctx_copied = deepcopy(ctx_dummy)
643 obj_decoded, tail = obj_expled.hexdecode(
644 obj_expled_hex_encoded + hexenc(tail_junk),
648 self.assertDictEqual(ctx_copied, ctx_dummy)
650 list(obj_decoded.pps())
651 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
652 self.assertEqual(tail, tail_junk)
653 self.assertEqual(obj_decoded, obj_expled)
654 self.assertNotEqual(obj_decoded, obj)
655 self.assertEqual(bool(obj_decoded), bool(obj_expled))
656 self.assertEqual(bool(obj_decoded), bool(obj))
657 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
658 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
659 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
661 obj_decoded.expl_llen,
662 len(len_encode(len(obj_encoded))),
664 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
665 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
668 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
670 self.assertEqual(obj_decoded.expl_offset, offset)
671 assert_exceeding_data(
673 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
677 evgens = list(obj_expled.decode_evgen(
678 hexdec(obj_expled_hex_encoded) + tail_junk,
680 decode_path=decode_path,
683 self.assertEqual(len(evgens), 1)
684 _decode_path, obj, tail = evgens[0]
685 self.assertSequenceEqual(tail, tail_junk)
686 self.assertEqual(_decode_path, decode_path)
687 self.assertEqual(obj, obj_decoded)
688 self.assertEqual(obj.expl_offset, offset)
692 @given(integers(min_value=2))
693 def test_invalid_len(self, l):
694 with self.assertRaises(InvalidLength):
695 Boolean().decode(b"".join((
701 @given(integers(min_value=0 + 1, max_value=255 - 1))
702 def test_ber_value(self, value):
703 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
704 Boolean().decode(b"".join((
714 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
715 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
716 self.assertTrue(bool(obj))
717 self.assertTrue(obj.ber_encoded)
718 self.assertFalse(obj.lenindef)
719 self.assertTrue(obj.bered)
721 self.assertTrue(obj.ber_encoded)
722 self.assertFalse(obj.lenindef)
723 self.assertTrue(obj.bered)
726 integers(min_value=1).map(tag_ctxc),
727 binary().filter(lambda x: not x.startswith(EOC)),
729 def test_ber_expl_no_eoc(self, expl, junk):
730 encoded = expl + LENINDEF + Boolean(False).encode()
731 with self.assertRaises(LenIndefForm):
732 Boolean(expl=expl).decode(encoded + junk)
733 with assertRaisesRegex(self, DecodeError, "no EOC"):
734 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
735 obj, tail = Boolean(expl=expl).decode(
736 encoded + EOC + junk,
739 self.assertTrue(obj.expl_lenindef)
740 self.assertFalse(obj.lenindef)
741 self.assertFalse(obj.ber_encoded)
742 self.assertTrue(obj.bered)
744 self.assertTrue(obj.expl_lenindef)
745 self.assertFalse(obj.lenindef)
746 self.assertFalse(obj.ber_encoded)
747 self.assertTrue(obj.bered)
748 self.assertSequenceEqual(tail, junk)
751 pprint(obj, big_blobs=True, with_decode_path=True)
754 integers(min_value=1).map(tag_ctxc),
761 def test_ber_expl(self, expl, values):
767 Boolean(value).encode() +
770 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
772 class SeqOf(SequenceOf):
773 schema = Boolean(expl=expl)
774 with self.assertRaises(LenIndefForm):
775 SeqOf().decode(encoded)
776 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
777 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
778 self.assertSequenceEqual(tail, b"")
779 self.assertSequenceEqual([bool(v) for v in seqof], values)
795 len(expl) + 1 + 3 + EOC_LEN,
806 pprint(seqof, big_blobs=True, with_decode_path=True)
810 def integer_values_strategy(draw, do_expl=False):
811 bound_min, value, default, bound_max = sorted(draw(sets(
820 _specs = draw(sets(text_letters()))
823 min_size=len(_specs),
824 max_size=len(_specs),
826 _specs = list(zip(_specs, values))
829 bounds = (bound_min, bound_max)
833 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
835 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
838 optional = draw(one_of(none(), booleans()))
840 draw(integers(min_value=0)),
841 draw(integers(min_value=0)),
842 draw(integers(min_value=0)),
844 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
847 class IntegerInherited(Integer):
851 class TestInteger(CommonMixin, TestCase):
854 def test_invalid_value_type(self):
855 with self.assertRaises(InvalidValueType) as err:
859 @given(sets(text_letters(), min_size=2))
860 def test_unknown_name(self, names_input):
861 missing = names_input.pop()
864 schema = [(n, 123) for n in names_input]
865 with self.assertRaises(ObjUnknown) as err:
869 @given(sets(text_letters(), min_size=2))
870 def test_known_name(self, names_input):
872 schema = [(n, 123) for n in names_input]
873 Int(names_input.pop())
876 def test_optional(self, optional):
877 obj = Integer(default=Integer(0), optional=optional)
878 self.assertTrue(obj.optional)
881 def test_ready(self, value):
883 self.assertFalse(obj.ready)
886 pprint(obj, big_blobs=True, with_decode_path=True)
887 with self.assertRaises(ObjNotReady) as err:
889 with self.assertRaises(ObjNotReady) as err:
893 self.assertTrue(obj.ready)
896 pprint(obj, big_blobs=True, with_decode_path=True)
899 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
900 def test_comparison(self, value1, value2, tag1, tag2):
901 for klass in (Integer, IntegerInherited):
904 self.assertEqual(obj1 == obj2, value1 == value2)
905 self.assertEqual(obj1 != obj2, value1 != value2)
906 self.assertEqual(obj1 == int(obj2), value1 == value2)
907 obj1 = klass(value1, impl=tag1)
908 obj2 = klass(value1, impl=tag2)
909 self.assertEqual(obj1 == obj2, tag1 == tag2)
910 self.assertEqual(obj1 != obj2, tag1 != tag2)
912 @given(lists(integers()))
913 def test_sorted_works(self, values):
914 self.assertSequenceEqual(
915 [int(v) for v in sorted(Integer(v) for v in values)],
919 @given(data_strategy())
920 def test_named(self, d):
921 names_input = list(d.draw(sets(text_letters(), min_size=1)))
922 values_input = list(d.draw(sets(
924 min_size=len(names_input),
925 max_size=len(names_input),
927 chosen_name = d.draw(sampled_from(names_input))
928 names_input = dict(zip(names_input, values_input))
932 _int = Int(chosen_name)
933 self.assertEqual(_int.named, chosen_name)
934 self.assertEqual(int(_int), names_input[chosen_name])
936 @given(integers(), integers(min_value=0), integers(min_value=0))
937 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
938 value = bound_min + value_delta
939 bound_max = value + bound_delta
940 Integer(value=value, bounds=(bound_min, bound_max))
942 @given(sets(integers(), min_size=3, max_size=3))
943 def test_bounds_unsatisfied(self, values):
944 values = sorted(values)
945 with self.assertRaises(BoundsError) as err:
946 Integer(value=values[0], bounds=(values[1], values[2]))
948 with assertRaisesRegex(self, DecodeError, "bounds") as err:
949 Integer(bounds=(values[1], values[2])).decode(
950 Integer(values[0]).encode()
953 with assertRaisesRegex(self, DecodeError, "bounds") as err:
954 Integer(bounds=(values[1], values[2])).decode(
955 encode2pass(Integer(values[0]))
957 with self.assertRaises(BoundsError) as err:
958 Integer(value=values[2], bounds=(values[0], values[1]))
960 with assertRaisesRegex(self, DecodeError, "bounds") as err:
961 Integer(bounds=(values[0], values[1])).decode(
962 Integer(values[2]).encode()
965 with assertRaisesRegex(self, DecodeError, "bounds") as err:
966 Integer(bounds=(values[0], values[1])).decode(
967 encode2pass(Integer(values[2]))
970 @given(data_strategy())
971 def test_call(self, d):
972 for klass in (Integer, IntegerInherited):
982 ) = d.draw(integer_values_strategy())
989 optional_initial or False,
1002 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
1003 if (default is None) and (obj_initial.default is not None):
1006 (bounds is None) and
1007 (value is not None) and
1008 (bounds_initial is not None) and
1009 not (bounds_initial[0] <= value <= bounds_initial[1])
1013 (bounds is None) and
1014 (default is not None) and
1015 (bounds_initial is not None) and
1016 not (bounds_initial[0] <= default <= bounds_initial[1])
1019 obj = obj_initial(value, bounds, impl, expl, default, optional)
1021 value_expected = default if value is None else value
1023 default_initial if value_expected is None
1026 self.assertEqual(obj, value_expected)
1027 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1028 self.assertEqual(obj.expl_tag, expl or expl_initial)
1031 default_initial if default is None else default,
1033 if obj.default is None:
1034 optional = optional_initial if optional is None else optional
1035 optional = False if optional is None else optional
1038 self.assertEqual(obj.optional, optional)
1040 (obj._bound_min, obj._bound_max),
1041 bounds or bounds_initial or (float("-inf"), float("+inf")),
1045 {} if _specs_initial is None else dict(_specs_initial),
1048 @given(integer_values_strategy())
1049 def test_copy(self, values):
1050 for klass in (Integer, IntegerInherited):
1051 obj = klass(*values)
1052 for copy_func in copy_funcs:
1053 obj_copied = copy_func(obj)
1054 self.assert_copied_basic_fields(obj, obj_copied)
1055 self.assertEqual(obj.specs, obj_copied.specs)
1056 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1057 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1058 self.assertEqual(obj._value, obj_copied._value)
1062 integers(min_value=1).map(tag_encode),
1064 def test_stripped(self, value, tag_impl):
1065 obj = Integer(value, impl=tag_impl)
1066 with self.assertRaises(NotEnoughData):
1067 obj.decode(obj.encode()[:-1])
1071 integers(min_value=1).map(tag_ctxc),
1073 def test_stripped_expl(self, value, tag_expl):
1074 obj = Integer(value, expl=tag_expl)
1075 with self.assertRaises(NotEnoughData):
1076 obj.decode(obj.encode()[:-1])
1078 def test_zero_len(self):
1079 with self.assertRaises(NotEnoughData):
1080 Integer().decode(b"".join((
1081 Integer.tag_default,
1086 integers(min_value=31),
1087 integers(min_value=0),
1090 def test_bad_tag(self, tag, offset, decode_path):
1091 with self.assertRaises(DecodeError) as err:
1093 tag_encode(tag)[:-1],
1095 decode_path=decode_path,
1098 self.assertEqual(err.exception.offset, offset)
1099 self.assertEqual(err.exception.decode_path, decode_path)
1102 integers(min_value=128),
1103 integers(min_value=0),
1106 def test_bad_len(self, l, offset, decode_path):
1107 with self.assertRaises(DecodeError) as err:
1109 Integer.tag_default + len_encode(l)[:-1],
1111 decode_path=decode_path,
1114 self.assertEqual(err.exception.offset, offset)
1115 self.assertEqual(err.exception.decode_path, decode_path)
1118 sets(integers(), min_size=2, max_size=2),
1119 integers(min_value=0),
1122 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1123 value, bound_min = list(sorted(ints))
1126 bounds = (bound_min, bound_min)
1127 with self.assertRaises(DecodeError) as err:
1129 Integer(value).encode(),
1131 decode_path=decode_path,
1134 self.assertEqual(err.exception.offset, offset)
1135 self.assertEqual(err.exception.decode_path, decode_path)
1137 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1139 integer_values_strategy(),
1141 integers(min_value=1).map(tag_ctxc),
1142 integers(min_value=0),
1146 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1147 for klass in (Integer, IntegerInherited):
1148 _, _, _, _, default, optional, _, _decoded = values
1157 pprint(obj, big_blobs=True, with_decode_path=True)
1158 self.assertFalse(obj.expled)
1159 obj_encoded = obj.encode()
1160 self.assertEqual(encode2pass(obj), obj_encoded)
1161 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1162 obj_expled = obj(value, expl=tag_expl)
1163 self.assertTrue(obj_expled.expled)
1165 list(obj_expled.pps())
1166 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1167 obj_expled_encoded = obj_expled.encode()
1168 obj_expled_cer = encode_cer(obj_expled)
1169 self.assertNotEqual(obj_expled_cer, obj_encoded)
1170 self.assertSequenceEqual(
1171 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1174 ctx_copied = deepcopy(ctx_dummy)
1175 obj_decoded, tail = obj_expled.decode(
1176 obj_expled_encoded + tail_junk,
1180 self.assertDictEqual(ctx_copied, ctx_dummy)
1182 list(obj_decoded.pps())
1183 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1184 self.assertEqual(tail, tail_junk)
1185 self.assertEqual(obj_decoded, obj_expled)
1186 self.assertNotEqual(obj_decoded, obj)
1187 self.assertEqual(int(obj_decoded), int(obj_expled))
1188 self.assertEqual(int(obj_decoded), int(obj))
1189 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1190 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1191 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1193 obj_decoded.expl_llen,
1194 len(len_encode(len(obj_encoded))),
1196 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1197 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1200 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1202 self.assertEqual(obj_decoded.expl_offset, offset)
1203 assert_exceeding_data(
1205 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1209 evgens = list(obj_expled.decode_evgen(
1210 obj_expled_encoded + tail_junk,
1212 decode_path=decode_path,
1215 self.assertEqual(len(evgens), 1)
1216 _decode_path, obj, tail = evgens[0]
1217 self.assertSequenceEqual(tail, tail_junk)
1218 self.assertEqual(_decode_path, decode_path)
1219 self.assertEqual(obj, obj_decoded)
1220 self.assertEqual(obj.expl_offset, offset)
1224 def test_go_vectors_valid(self):
1225 for data, expect in ((
1229 (b"\xff\x7f", -129),
1233 (b"\xff\x00", -256),
1237 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1238 (b"\x80\x00\x00\x00", -2147483648),
1241 Integer().decode(b"".join((
1242 Integer.tag_default,
1243 len_encode(len(data)),
1249 def test_go_vectors_invalid(self):
1254 with self.assertRaises(DecodeError):
1255 Integer().decode(b"".join((
1256 Integer.tag_default,
1257 len_encode(len(data)),
1263 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1266 if draw(booleans()):
1267 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1269 integers(min_value=0, max_value=255),
1270 min_size=len(schema),
1271 max_size=len(schema),
1273 schema = list(zip(schema, bits))
1275 def _value(value_required):
1276 if not value_required and draw(booleans()):
1278 generation_choice = 0
1280 generation_choice = draw(sampled_from((1, 2, 3)))
1281 if generation_choice == 1 or draw(booleans()):
1282 return "'%s'B" % "".join(draw(lists(
1283 sampled_from(("0", "1")),
1284 max_size=len(schema),
1286 if generation_choice == 2 or draw(booleans()):
1287 return draw(binary(max_size=len(schema) // 8))
1288 if generation_choice == 3 or draw(booleans()):
1289 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1291 value = _value(value_required)
1292 default = _value(value_required=False)
1296 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1298 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1299 optional = draw(one_of(none(), booleans()))
1301 draw(integers(min_value=0)),
1302 draw(integers(min_value=0)),
1303 draw(integers(min_value=0)),
1305 return (schema, value, impl, expl, default, optional, _decoded)
1308 class BitStringInherited(BitString):
1312 class TestBitString(CommonMixin, TestCase):
1313 base_klass = BitString
1315 @given(lists(booleans()))
1316 def test_b_encoding(self, bits):
1317 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1318 self.assertEqual(obj.bit_len, len(bits))
1319 self.assertSequenceEqual(list(obj), bits)
1320 for i, bit in enumerate(bits):
1321 self.assertEqual(obj[i], bit)
1323 @given(lists(booleans()))
1324 def test_out_of_bounds_bits(self, bits):
1325 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1326 for i in range(len(bits), len(bits) * 2):
1327 self.assertFalse(obj[i])
1329 def test_bad_b_encoding(self):
1330 with self.assertRaises(ValueError):
1331 BitString("'010120101'B")
1334 integers(min_value=1, max_value=255),
1335 integers(min_value=1, max_value=255),
1337 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1338 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1339 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1340 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1342 class BS(BitString):
1343 schema = (("whatever", 0),)
1344 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1345 self.assertEqual(obj.bit_len, leading_zeros + 1)
1346 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1348 def test_zero_len(self):
1349 with self.assertRaises(NotEnoughData):
1350 BitString().decode(b"".join((
1351 BitString.tag_default,
1355 def test_invalid_value_type(self):
1356 with self.assertRaises(InvalidValueType) as err:
1359 with self.assertRaises(InvalidValueType) as err:
1363 def test_obj_unknown(self):
1364 with self.assertRaises(ObjUnknown) as err:
1365 BitString(b"whatever")["whenever"]
1368 def test_get_invalid_type(self):
1369 with self.assertRaises(InvalidValueType) as err:
1370 BitString(b"whatever")[(1, 2, 3)]
1373 @given(data_strategy())
1374 def test_unknown_name(self, d):
1375 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1376 missing = _schema.pop()
1378 class BS(BitString):
1379 schema = [(n, i) for i, n in enumerate(_schema)]
1380 with self.assertRaises(ObjUnknown) as err:
1385 def test_optional(self, optional):
1386 obj = BitString(default=BitString(b""), optional=optional)
1387 self.assertTrue(obj.optional)
1390 def test_ready(self, value):
1392 self.assertFalse(obj.ready)
1395 pprint(obj, big_blobs=True, with_decode_path=True)
1396 with self.assertRaises(ObjNotReady) as err:
1399 with self.assertRaises(ObjNotReady) as err:
1401 obj = BitString(value)
1402 self.assertTrue(obj.ready)
1405 pprint(obj, big_blobs=True, with_decode_path=True)
1408 tuples(integers(min_value=0), binary()),
1409 tuples(integers(min_value=0), binary()),
1413 def test_comparison(self, value1, value2, tag1, tag2):
1414 for klass in (BitString, BitStringInherited):
1415 obj1 = klass(value1)
1416 obj2 = klass(value2)
1417 self.assertEqual(obj1 == obj2, value1 == value2)
1418 self.assertEqual(obj1 != obj2, value1 != value2)
1419 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1420 obj1 = klass(value1, impl=tag1)
1421 obj2 = klass(value1, impl=tag2)
1422 self.assertEqual(obj1 == obj2, tag1 == tag2)
1423 self.assertEqual(obj1 != obj2, tag1 != tag2)
1425 @given(data_strategy())
1426 def test_call(self, d):
1427 for klass in (BitString, BitStringInherited):
1436 ) = d.draw(bit_string_values_strategy())
1439 schema = schema_initial
1441 value=value_initial,
1444 default=default_initial,
1445 optional=optional_initial or False,
1446 _decoded=_decoded_initial,
1456 ) = d.draw(bit_string_values_strategy(
1457 schema=schema_initial,
1458 do_expl=impl_initial is None,
1467 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1468 self.assertEqual(obj.expl_tag, expl or expl_initial)
1469 if obj.default is None:
1470 optional = optional_initial if optional is None else optional
1471 optional = False if optional is None else optional
1474 self.assertEqual(obj.optional, optional)
1475 self.assertEqual(obj.specs, obj_initial.specs)
1477 @given(bit_string_values_strategy())
1478 def test_copy(self, values):
1479 for klass in (BitString, BitStringInherited):
1480 _schema, value, impl, expl, default, optional, _decoded = values
1490 optional=optional or False,
1493 for copy_func in copy_funcs:
1494 obj_copied = copy_func(obj)
1495 self.assert_copied_basic_fields(obj, obj_copied)
1496 self.assertEqual(obj.specs, obj_copied.specs)
1497 self.assertEqual(obj._value, obj_copied._value)
1501 integers(min_value=1).map(tag_encode),
1503 def test_stripped(self, value, tag_impl):
1504 obj = BitString(value, impl=tag_impl)
1505 with self.assertRaises(NotEnoughData):
1506 obj.decode(obj.encode()[:-1])
1510 integers(min_value=1).map(tag_ctxc),
1512 def test_stripped_expl(self, value, tag_expl):
1513 obj = BitString(value, expl=tag_expl)
1514 with self.assertRaises(NotEnoughData):
1515 obj.decode(obj.encode()[:-1])
1518 integers(min_value=31),
1519 integers(min_value=0),
1522 def test_bad_tag(self, tag, offset, decode_path):
1523 with self.assertRaises(DecodeError) as err:
1525 tag_encode(tag)[:-1],
1527 decode_path=decode_path,
1530 self.assertEqual(err.exception.offset, offset)
1531 self.assertEqual(err.exception.decode_path, decode_path)
1534 integers(min_value=128),
1535 integers(min_value=0),
1538 def test_bad_len(self, l, offset, decode_path):
1539 with self.assertRaises(DecodeError) as err:
1541 BitString.tag_default + len_encode(l)[:-1],
1543 decode_path=decode_path,
1546 self.assertEqual(err.exception.offset, offset)
1547 self.assertEqual(err.exception.decode_path, decode_path)
1549 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1550 @given(data_strategy())
1551 def test_symmetric(self, d):
1560 ) = d.draw(bit_string_values_strategy(value_required=True))
1561 tail_junk = d.draw(binary(max_size=5))
1562 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1563 offset = d.draw(integers(min_value=0))
1564 decode_path = d.draw(decode_path_strat)
1565 for klass in (BitString, BitStringInherited):
1576 pprint(obj, big_blobs=True, with_decode_path=True)
1577 self.assertFalse(obj.expled)
1578 obj_encoded = obj.encode()
1579 self.assertEqual(encode2pass(obj), obj_encoded)
1580 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1581 obj_expled = obj(value, expl=tag_expl)
1582 self.assertTrue(obj_expled.expled)
1584 list(obj_expled.pps())
1585 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1586 obj_expled_encoded = obj_expled.encode()
1587 obj_expled_cer = encode_cer(obj_expled)
1588 self.assertNotEqual(obj_expled_cer, obj_encoded)
1589 self.assertSequenceEqual(
1590 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1593 ctx_copied = deepcopy(ctx_dummy)
1594 obj_decoded, tail = obj_expled.decode(
1595 obj_expled_encoded + tail_junk,
1599 self.assertDictEqual(ctx_copied, ctx_dummy)
1601 list(obj_decoded.pps())
1602 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1603 self.assertEqual(tail, tail_junk)
1604 self.assertEqual(obj_decoded, obj_expled)
1605 self.assertNotEqual(obj_decoded, obj)
1606 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1607 self.assertEqual(bytes(obj_decoded), bytes(obj))
1608 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1609 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1610 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1612 obj_decoded.expl_llen,
1613 len(len_encode(len(obj_encoded))),
1615 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1616 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1619 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1621 self.assertEqual(obj_decoded.expl_offset, offset)
1622 if isinstance(value, tuple):
1623 self.assertSetEqual(set(value), set(obj_decoded.named))
1626 assert_exceeding_data(
1628 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1632 evgens = list(obj_expled.decode_evgen(
1633 obj_expled_encoded + tail_junk,
1635 decode_path=decode_path,
1638 self.assertEqual(len(evgens), 1)
1639 _decode_path, obj, tail = evgens[0]
1640 self.assertSequenceEqual(tail, tail_junk)
1641 self.assertEqual(_decode_path, decode_path)
1642 self.assertEqual(obj.expl_offset, offset)
1646 @given(integers(min_value=1, max_value=255))
1647 def test_bad_zero_value(self, pad_size):
1648 with self.assertRaises(DecodeError):
1649 BitString().decode(b"".join((
1650 BitString.tag_default,
1655 def test_go_vectors_invalid(self):
1661 with self.assertRaises(DecodeError):
1662 BitString().decode(b"".join((
1663 BitString.tag_default,
1668 def test_go_vectors_valid(self):
1669 obj, _ = BitString().decode(b"".join((
1670 BitString.tag_default,
1674 self.assertEqual(bytes(obj), b"")
1675 self.assertEqual(obj.bit_len, 0)
1677 obj, _ = BitString().decode(b"".join((
1678 BitString.tag_default,
1682 self.assertEqual(bytes(obj), b"\x00")
1683 self.assertEqual(obj.bit_len, 1)
1685 obj = BitString((16, b"\x82\x40"))
1686 self.assertTrue(obj[0])
1687 self.assertFalse(obj[1])
1688 self.assertTrue(obj[6])
1689 self.assertTrue(obj[9])
1690 self.assertFalse(obj[17])
1692 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1694 integers(min_value=1, max_value=30),
1697 binary(min_size=1, max_size=5),
1699 binary(min_size=1, max_size=5),
1707 lists(booleans(), min_size=1),
1711 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1712 def chunk_constructed(contents):
1714 tag_encode(form=TagFormConstructed, num=3) +
1716 b"".join(BitString(content).encode() for content in contents) +
1720 chunks_len_expected = []
1721 payload_expected = b""
1722 bit_len_expected = 0
1723 for chunk_input in chunk_inputs:
1724 if isinstance(chunk_input, binary_type):
1725 chunks.append(BitString(chunk_input).encode())
1726 payload_expected += chunk_input
1727 bit_len_expected += len(chunk_input) * 8
1728 chunks_len_expected.append(len(chunk_input) + 1)
1730 chunks.append(chunk_constructed(chunk_input))
1731 payload = b"".join(chunk_input)
1732 payload_expected += payload
1733 bit_len_expected += len(payload) * 8
1734 for c in chunk_input:
1735 chunks_len_expected.append(len(c) + 1)
1736 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1737 chunk_last = BitString("'%s'B" % "".join(
1738 "1" if bit else "0" for bit in chunk_last_bits
1740 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1741 payload_expected += bytes(chunk_last)
1742 bit_len_expected += chunk_last.bit_len
1743 encoded_indefinite = (
1744 tag_encode(form=TagFormConstructed, num=impl) +
1747 chunk_last.encode() +
1750 encoded_definite = (
1751 tag_encode(form=TagFormConstructed, num=impl) +
1752 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1756 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1757 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1758 for lenindef_expected, encoded in (
1759 (True, encoded_indefinite),
1760 (False, encoded_definite),
1762 obj, tail = BitString(impl=tag_encode(impl)).decode(
1764 ctx={"bered": True},
1766 self.assertSequenceEqual(tail, junk)
1767 self.assertEqual(obj.bit_len, bit_len_expected)
1768 self.assertSequenceEqual(bytes(obj), payload_expected)
1769 self.assertTrue(obj.ber_encoded)
1770 self.assertEqual(obj.lenindef, lenindef_expected)
1771 self.assertTrue(obj.bered)
1773 self.assertTrue(obj.ber_encoded)
1774 self.assertEqual(obj.lenindef, lenindef_expected)
1775 self.assertTrue(obj.bered)
1776 self.assertEqual(len(encoded), obj.tlvlen)
1779 pprint(obj, big_blobs=True, with_decode_path=True)
1781 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1783 decode_path=decode_path,
1784 ctx={"bered": True},
1786 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1787 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1788 self.assertGreater(len(dp), len(decode_path))
1789 self.assertEqual(obj.vlen, chunk_len_expected)
1792 integers(min_value=0),
1795 def test_ber_definite_too_short(self, offset, decode_path):
1796 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1798 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1800 decode_path=decode_path,
1801 ctx={"bered": True},
1803 self.assertEqual(err.exception.decode_path, decode_path)
1804 self.assertEqual(err.exception.offset, offset)
1807 integers(min_value=0),
1810 def test_ber_definite_no_data(self, offset, decode_path):
1811 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1813 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1815 decode_path=decode_path,
1816 ctx={"bered": True},
1818 self.assertEqual(err.exception.decode_path, decode_path)
1819 self.assertEqual(err.exception.offset, offset)
1822 integers(min_value=0),
1824 integers(min_value=1, max_value=3),
1826 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1827 bs = BitString(b"data").encode()
1828 with self.assertRaises(NotEnoughData) as err:
1830 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1832 decode_path=decode_path,
1833 ctx={"bered": True},
1835 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1836 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1839 integers(min_value=0),
1841 integers(min_value=1, max_value=3),
1843 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1844 bs = BitString(b"data").encode()
1845 bs_longer = BitString(b"data-longer").encode()
1846 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1849 tag_encode(3, form=TagFormConstructed) +
1850 len_encode((chunks + 1) * len(bs)) +
1855 decode_path=decode_path,
1856 ctx={"bered": True},
1858 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1859 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1862 integers(min_value=0),
1865 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1866 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1868 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1870 decode_path=decode_path,
1871 ctx={"bered": True},
1873 self.assertEqual(err.exception.decode_path, decode_path)
1874 self.assertEqual(err.exception.offset, offset)
1876 @given(data_strategy())
1877 def test_ber_indefinite_not_multiple(self, d):
1878 bs_short = BitString("'A'H").encode()
1879 bs_full = BitString("'AA'H").encode()
1880 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1881 chunks.append(bs_short)
1882 d.draw(permutations(chunks))
1883 chunks.append(bs_short)
1884 offset = d.draw(integers(min_value=0))
1885 decode_path = d.draw(decode_path_strat)
1886 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1889 tag_encode(3, form=TagFormConstructed) +
1895 decode_path=decode_path,
1896 ctx={"bered": True},
1899 err.exception.decode_path,
1900 decode_path + (str(chunks.index(bs_short)),),
1903 err.exception.offset,
1904 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1907 def test_x690_vector(self):
1908 vector = BitString("'0A3B5F291CD'H")
1909 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1910 self.assertSequenceEqual(tail, b"")
1911 self.assertEqual(obj, vector)
1912 obj, tail = BitString().decode(
1913 hexdec("23800303000A3B0305045F291CD00000"),
1914 ctx={"bered": True},
1916 self.assertSequenceEqual(tail, b"")
1917 self.assertEqual(obj, vector)
1918 self.assertTrue(obj.ber_encoded)
1919 self.assertTrue(obj.lenindef)
1920 self.assertTrue(obj.bered)
1922 self.assertTrue(obj.ber_encoded)
1923 self.assertTrue(obj.lenindef)
1924 self.assertTrue(obj.bered)
1926 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1927 @given(integers(min_value=1000, max_value=3000))
1928 def test_cer(self, data_len):
1929 data = urandom(data_len)
1930 encoded = encode_cer(BitString(data))
1931 ctx = {"bered": True}
1932 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1933 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1934 evgens_expected = data_len // 999
1935 if evgens_expected * 999 != data_len:
1936 evgens_expected += 1
1937 evgens_expected += 1
1938 self.assertEqual(len(evgens), evgens_expected)
1939 for (_, obj, _) in evgens[:-2]:
1940 self.assertEqual(obj.vlen, 1000)
1941 _, obj, _ = evgens[-2]
1942 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1946 def octet_string_values_strategy(draw, do_expl=False):
1947 bound_min, bound_max = sorted(draw(sets(
1948 integers(min_value=0, max_value=1 << 7),
1952 value = draw(one_of(
1954 binary(min_size=bound_min, max_size=bound_max),
1956 default = draw(one_of(
1958 binary(min_size=bound_min, max_size=bound_max),
1961 if draw(booleans()):
1962 bounds = (bound_min, bound_max)
1966 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1968 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1969 optional = draw(one_of(none(), booleans()))
1971 draw(integers(min_value=0)),
1972 draw(integers(min_value=0)),
1973 draw(integers(min_value=0)),
1975 return (value, bounds, impl, expl, default, optional, _decoded)
1978 class OctetStringInherited(OctetString):
1982 class TestOctetString(CommonMixin, TestCase):
1983 base_klass = OctetString
1985 def test_invalid_value_type(self):
1986 with self.assertRaises(InvalidValueType) as err:
1987 OctetString(text_type(123))
1991 def test_optional(self, optional):
1992 obj = OctetString(default=OctetString(b""), optional=optional)
1993 self.assertTrue(obj.optional)
1996 def test_ready(self, value):
1998 self.assertFalse(obj.ready)
2001 pprint(obj, big_blobs=True, with_decode_path=True)
2002 with self.assertRaises(ObjNotReady) as err:
2005 with self.assertRaises(ObjNotReady) as err:
2007 obj = OctetString(value)
2008 self.assertTrue(obj.ready)
2011 pprint(obj, big_blobs=True, with_decode_path=True)
2013 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2014 def test_comparison(self, value1, value2, tag1, tag2):
2015 for klass in (OctetString, OctetStringInherited):
2016 obj1 = klass(value1)
2017 obj2 = klass(value2)
2018 self.assertEqual(obj1 == obj2, value1 == value2)
2019 self.assertEqual(obj1 != obj2, value1 != value2)
2020 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2021 obj1 = klass(value1, impl=tag1)
2022 obj2 = klass(value1, impl=tag2)
2023 self.assertEqual(obj1 == obj2, tag1 == tag2)
2024 self.assertEqual(obj1 != obj2, tag1 != tag2)
2026 @given(lists(binary()))
2027 def test_sorted_works(self, values):
2028 self.assertSequenceEqual(
2029 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2033 @given(data_strategy())
2034 def test_bounds_satisfied(self, d):
2035 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2036 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2037 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2038 OctetString(value=value, bounds=(bound_min, bound_max))
2040 @given(data_strategy())
2041 def test_bounds_unsatisfied(self, d):
2042 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2043 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2044 value = d.draw(binary(max_size=bound_min - 1))
2045 with self.assertRaises(BoundsError) as err:
2046 OctetString(value=value, bounds=(bound_min, bound_max))
2048 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2049 OctetString(bounds=(bound_min, bound_max)).decode(
2050 OctetString(value).encode()
2053 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2054 OctetString(bounds=(bound_min, bound_max)).decode(
2055 encode2pass(OctetString(value))
2057 value = d.draw(binary(min_size=bound_max + 1))
2058 with self.assertRaises(BoundsError) as err:
2059 OctetString(value=value, bounds=(bound_min, bound_max))
2061 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2062 OctetString(bounds=(bound_min, bound_max)).decode(
2063 OctetString(value).encode()
2066 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2067 OctetString(bounds=(bound_min, bound_max)).decode(
2068 encode2pass(OctetString(value))
2071 @given(data_strategy())
2072 def test_call(self, d):
2073 for klass in (OctetString, OctetStringInherited):
2082 ) = d.draw(octet_string_values_strategy())
2083 obj_initial = klass(
2089 optional_initial or False,
2100 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2101 if (default is None) and (obj_initial.default is not None):
2104 (bounds is None) and
2105 (value is not None) and
2106 (bounds_initial is not None) and
2107 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2111 (bounds is None) and
2112 (default is not None) and
2113 (bounds_initial is not None) and
2114 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2117 obj = obj_initial(value, bounds, impl, expl, default, optional)
2119 value_expected = default if value is None else value
2121 default_initial if value_expected is None
2124 self.assertEqual(obj, value_expected)
2125 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2126 self.assertEqual(obj.expl_tag, expl or expl_initial)
2129 default_initial if default is None else default,
2131 if obj.default is None:
2132 optional = optional_initial if optional is None else optional
2133 optional = False if optional is None else optional
2136 self.assertEqual(obj.optional, optional)
2138 (obj._bound_min, obj._bound_max),
2139 bounds or bounds_initial or (0, float("+inf")),
2142 @given(octet_string_values_strategy())
2143 def test_copy(self, values):
2144 for klass in (OctetString, OctetStringInherited):
2145 obj = klass(*values)
2146 for copy_func in copy_funcs:
2147 obj_copied = copy_func(obj)
2148 self.assert_copied_basic_fields(obj, obj_copied)
2149 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2150 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2151 self.assertEqual(obj._value, obj_copied._value)
2155 integers(min_value=1).map(tag_encode),
2157 def test_stripped(self, value, tag_impl):
2158 obj = OctetString(value, impl=tag_impl)
2159 with self.assertRaises(NotEnoughData):
2160 obj.decode(obj.encode()[:-1])
2164 integers(min_value=1).map(tag_ctxc),
2166 def test_stripped_expl(self, value, tag_expl):
2167 obj = OctetString(value, expl=tag_expl)
2168 with self.assertRaises(NotEnoughData):
2169 obj.decode(obj.encode()[:-1])
2172 integers(min_value=31),
2173 integers(min_value=0),
2176 def test_bad_tag(self, tag, offset, decode_path):
2177 with self.assertRaises(DecodeError) as err:
2178 OctetString().decode(
2179 tag_encode(tag)[:-1],
2181 decode_path=decode_path,
2184 self.assertEqual(err.exception.offset, offset)
2185 self.assertEqual(err.exception.decode_path, decode_path)
2188 integers(min_value=128),
2189 integers(min_value=0),
2192 def test_bad_len(self, l, offset, decode_path):
2193 with self.assertRaises(DecodeError) as err:
2194 OctetString().decode(
2195 OctetString.tag_default + len_encode(l)[:-1],
2197 decode_path=decode_path,
2200 self.assertEqual(err.exception.offset, offset)
2201 self.assertEqual(err.exception.decode_path, decode_path)
2204 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2205 integers(min_value=0),
2208 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2209 value, bound_min = list(sorted(ints))
2211 class String(OctetString):
2212 bounds = (bound_min, bound_min)
2213 with self.assertRaises(DecodeError) as err:
2215 OctetString(b"\x00" * value).encode(),
2217 decode_path=decode_path,
2220 self.assertEqual(err.exception.offset, offset)
2221 self.assertEqual(err.exception.decode_path, decode_path)
2223 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2225 octet_string_values_strategy(),
2227 integers(min_value=1).map(tag_ctxc),
2228 integers(min_value=0),
2232 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2233 for klass in (OctetString, OctetStringInherited):
2234 _, _, _, _, default, optional, _decoded = values
2243 pprint(obj, big_blobs=True, with_decode_path=True)
2244 self.assertFalse(obj.expled)
2245 obj_encoded = obj.encode()
2246 self.assertEqual(encode2pass(obj), obj_encoded)
2247 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2248 obj_expled = obj(value, expl=tag_expl)
2249 self.assertTrue(obj_expled.expled)
2251 list(obj_expled.pps())
2252 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2253 obj_expled_encoded = obj_expled.encode()
2254 obj_expled_cer = encode_cer(obj_expled)
2255 self.assertNotEqual(obj_expled_cer, obj_encoded)
2256 self.assertSequenceEqual(
2257 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2260 ctx_copied = deepcopy(ctx_dummy)
2261 obj_decoded, tail = obj_expled.decode(
2262 obj_expled_encoded + tail_junk,
2266 self.assertDictEqual(ctx_copied, ctx_dummy)
2268 list(obj_decoded.pps())
2269 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2270 self.assertEqual(tail, tail_junk)
2271 self.assertEqual(obj_decoded, obj_expled)
2272 self.assertNotEqual(obj_decoded, obj)
2273 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2274 self.assertEqual(bytes(obj_decoded), bytes(obj))
2275 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2276 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2277 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2279 obj_decoded.expl_llen,
2280 len(len_encode(len(obj_encoded))),
2282 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2283 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2286 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2288 self.assertEqual(obj_decoded.expl_offset, offset)
2289 assert_exceeding_data(
2291 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2295 evgens = list(obj_expled.decode_evgen(
2296 obj_expled_encoded + tail_junk,
2298 decode_path=decode_path,
2301 self.assertEqual(len(evgens), 1)
2302 _decode_path, obj, tail = evgens[0]
2303 self.assertSequenceEqual(tail, tail_junk)
2304 self.assertEqual(_decode_path, decode_path)
2305 self.assertEqual(obj.expl_offset, offset)
2309 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2311 integers(min_value=1, max_value=30),
2314 binary(min_size=1, max_size=5),
2316 binary(min_size=1, max_size=5),
2327 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2328 def chunk_constructed(contents):
2330 tag_encode(form=TagFormConstructed, num=4) +
2332 b"".join(OctetString(content).encode() for content in contents) +
2336 chunks_len_expected = []
2337 payload_expected = b""
2338 for chunk_input in chunk_inputs:
2339 if isinstance(chunk_input, binary_type):
2340 chunks.append(OctetString(chunk_input).encode())
2341 payload_expected += chunk_input
2342 chunks_len_expected.append(len(chunk_input))
2344 chunks.append(chunk_constructed(chunk_input))
2345 payload = b"".join(chunk_input)
2346 payload_expected += payload
2347 for c in chunk_input:
2348 chunks_len_expected.append(len(c))
2349 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2350 encoded_indefinite = (
2351 tag_encode(form=TagFormConstructed, num=impl) +
2356 encoded_definite = (
2357 tag_encode(form=TagFormConstructed, num=impl) +
2358 len_encode(len(b"".join(chunks))) +
2361 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2362 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2363 for lenindef_expected, encoded in (
2364 (True, encoded_indefinite),
2365 (False, encoded_definite),
2367 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2369 ctx={"bered": True},
2371 self.assertSequenceEqual(tail, junk)
2372 self.assertSequenceEqual(bytes(obj), payload_expected)
2373 self.assertTrue(obj.ber_encoded)
2374 self.assertEqual(obj.lenindef, lenindef_expected)
2375 self.assertTrue(obj.bered)
2377 self.assertTrue(obj.ber_encoded)
2378 self.assertEqual(obj.lenindef, lenindef_expected)
2379 self.assertTrue(obj.bered)
2380 self.assertEqual(len(encoded), obj.tlvlen)
2383 pprint(obj, big_blobs=True, with_decode_path=True)
2385 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2387 decode_path=decode_path,
2388 ctx={"bered": True},
2390 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2391 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2392 self.assertGreater(len(dp), len(decode_path))
2393 self.assertEqual(obj.vlen, chunk_len_expected)
2396 integers(min_value=0),
2399 def test_ber_definite_too_short(self, offset, decode_path):
2400 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2401 OctetString().decode(
2402 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2404 decode_path=decode_path,
2405 ctx={"bered": True},
2407 self.assertEqual(err.exception.decode_path, decode_path)
2408 self.assertEqual(err.exception.offset, offset)
2411 integers(min_value=0),
2413 integers(min_value=1, max_value=3),
2415 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2416 bs = OctetString(b"data").encode()
2417 with self.assertRaises(NotEnoughData) as err:
2418 OctetString().decode(
2419 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2421 decode_path=decode_path,
2422 ctx={"bered": True},
2424 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2425 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2428 integers(min_value=0),
2430 integers(min_value=1, max_value=3),
2432 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2433 bs = OctetString(b"data").encode()
2434 bs_longer = OctetString(b"data-longer").encode()
2435 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2436 OctetString().decode(
2438 tag_encode(4, form=TagFormConstructed) +
2439 len_encode((chunks + 1) * len(bs)) +
2444 decode_path=decode_path,
2445 ctx={"bered": True},
2447 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2448 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2450 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2451 @given(integers(min_value=1001, max_value=3000))
2452 def test_cer(self, data_len):
2453 data = urandom(data_len)
2454 encoded = encode_cer(OctetString(data))
2455 ctx = {"bered": True}
2456 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2457 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2458 evgens_expected = data_len // 1000
2459 if evgens_expected * 1000 != data_len:
2460 evgens_expected += 1
2461 evgens_expected += 1
2462 self.assertEqual(len(evgens), evgens_expected)
2463 for (_, obj, _) in evgens[:-2]:
2464 self.assertEqual(obj.vlen, 1000)
2465 _, obj, _ = evgens[-2]
2466 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2470 def null_values_strategy(draw, do_expl=False):
2474 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2476 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2477 optional = draw(one_of(none(), booleans()))
2479 draw(integers(min_value=0)),
2480 draw(integers(min_value=0)),
2481 draw(integers(min_value=0)),
2483 return (impl, expl, optional, _decoded)
2486 class NullInherited(Null):
2490 class TestNull(CommonMixin, TestCase):
2493 def test_ready(self):
2495 self.assertTrue(obj.ready)
2498 pprint(obj, big_blobs=True, with_decode_path=True)
2500 @given(binary(min_size=1), binary(min_size=1))
2501 def test_comparison(self, tag1, tag2):
2502 for klass in (Null, NullInherited):
2503 obj1 = klass(impl=tag1)
2504 obj2 = klass(impl=tag2)
2505 self.assertEqual(obj1 == obj2, tag1 == tag2)
2506 self.assertEqual(obj1 != obj2, tag1 != tag2)
2507 self.assertNotEqual(obj1, tag2)
2509 @given(data_strategy())
2510 def test_call(self, d):
2511 for klass in (Null, NullInherited):
2517 ) = d.draw(null_values_strategy())
2518 obj_initial = klass(
2521 optional=optional_initial or False,
2522 _decoded=_decoded_initial,
2529 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2530 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2531 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2532 self.assertEqual(obj.expl_tag, expl or expl_initial)
2533 optional = optional_initial if optional is None else optional
2534 optional = False if optional is None else optional
2535 self.assertEqual(obj.optional, optional)
2537 @given(null_values_strategy())
2538 def test_copy(self, values):
2539 for klass in (Null, NullInherited):
2540 impl, expl, optional, _decoded = values
2544 optional=optional or False,
2547 for copy_func in copy_funcs:
2548 obj_copied = copy_func(obj)
2549 self.assert_copied_basic_fields(obj, obj_copied)
2551 @given(integers(min_value=1).map(tag_encode))
2552 def test_stripped(self, tag_impl):
2553 obj = Null(impl=tag_impl)
2554 with self.assertRaises(NotEnoughData):
2555 obj.decode(obj.encode()[:-1])
2557 @given(integers(min_value=1).map(tag_ctxc))
2558 def test_stripped_expl(self, tag_expl):
2559 obj = Null(expl=tag_expl)
2560 with self.assertRaises(NotEnoughData):
2561 obj.decode(obj.encode()[:-1])
2564 integers(min_value=31),
2565 integers(min_value=0),
2568 def test_bad_tag(self, tag, offset, decode_path):
2569 with self.assertRaises(DecodeError) as err:
2571 tag_encode(tag)[:-1],
2573 decode_path=decode_path,
2576 self.assertEqual(err.exception.offset, offset)
2577 self.assertEqual(err.exception.decode_path, decode_path)
2580 integers(min_value=128),
2581 integers(min_value=0),
2584 def test_bad_len(self, l, offset, decode_path):
2585 with self.assertRaises(DecodeError) as err:
2587 Null.tag_default + len_encode(l)[:-1],
2589 decode_path=decode_path,
2592 self.assertEqual(err.exception.offset, offset)
2593 self.assertEqual(err.exception.decode_path, decode_path)
2595 @given(binary(min_size=1))
2596 def test_tag_mismatch(self, impl):
2597 assume(impl != Null.tag_default)
2598 with self.assertRaises(TagMismatch):
2599 Null(impl=impl).decode(Null().encode())
2602 null_values_strategy(),
2603 integers(min_value=1).map(tag_ctxc),
2604 integers(min_value=0),
2608 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2609 for klass in (Null, NullInherited):
2610 _, _, optional, _decoded = values
2611 obj = klass(optional=optional, _decoded=_decoded)
2614 pprint(obj, big_blobs=True, with_decode_path=True)
2615 self.assertFalse(obj.expled)
2616 obj_encoded = obj.encode()
2617 self.assertEqual(encode2pass(obj), obj_encoded)
2618 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2619 obj_expled = obj(expl=tag_expl)
2620 self.assertTrue(obj_expled.expled)
2622 list(obj_expled.pps())
2623 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2624 obj_expled_encoded = obj_expled.encode()
2625 obj_expled_cer = encode_cer(obj_expled)
2626 self.assertNotEqual(obj_expled_cer, obj_encoded)
2627 self.assertSequenceEqual(
2628 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2631 ctx_copied = deepcopy(ctx_dummy)
2632 obj_decoded, tail = obj_expled.decode(
2633 obj_expled_encoded + tail_junk,
2637 self.assertDictEqual(ctx_copied, ctx_dummy)
2639 list(obj_decoded.pps())
2640 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2641 self.assertEqual(tail, tail_junk)
2642 self.assertEqual(obj_decoded, obj_expled)
2643 self.assertNotEqual(obj_decoded, obj)
2644 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2645 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2646 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2648 obj_decoded.expl_llen,
2649 len(len_encode(len(obj_encoded))),
2651 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2652 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2655 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2657 self.assertEqual(obj_decoded.expl_offset, offset)
2658 assert_exceeding_data(
2660 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2664 evgens = list(obj_expled.decode_evgen(
2665 obj_expled_encoded + tail_junk,
2667 decode_path=decode_path,
2670 self.assertEqual(len(evgens), 1)
2671 _decode_path, obj, tail = evgens[0]
2672 self.assertSequenceEqual(tail, tail_junk)
2673 self.assertEqual(_decode_path, decode_path)
2674 self.assertEqual(obj, obj_decoded)
2675 self.assertEqual(obj.expl_offset, offset)
2679 @given(integers(min_value=1))
2680 def test_invalid_len(self, l):
2681 with self.assertRaises(InvalidLength):
2682 Null().decode(b"".join((
2689 def oid_strategy(draw):
2690 first_arc = draw(integers(min_value=0, max_value=2))
2692 if first_arc in (0, 1):
2693 second_arc = draw(integers(min_value=0, max_value=39))
2695 second_arc = draw(integers(min_value=0))
2696 other_arcs = draw(lists(integers(min_value=0)))
2697 return tuple([first_arc, second_arc] + other_arcs)
2701 def oid_values_strategy(draw, do_expl=False):
2702 value = draw(one_of(none(), oid_strategy()))
2706 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2708 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2709 default = draw(one_of(none(), oid_strategy()))
2710 optional = draw(one_of(none(), booleans()))
2712 draw(integers(min_value=0)),
2713 draw(integers(min_value=0)),
2714 draw(integers(min_value=0)),
2716 return (value, impl, expl, default, optional, _decoded)
2719 class ObjectIdentifierInherited(ObjectIdentifier):
2723 class TestObjectIdentifier(CommonMixin, TestCase):
2724 base_klass = ObjectIdentifier
2726 def test_invalid_value_type(self):
2727 with self.assertRaises(InvalidValueType) as err:
2728 ObjectIdentifier(123)
2732 def test_optional(self, optional):
2733 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2734 self.assertTrue(obj.optional)
2736 @given(oid_strategy())
2737 def test_ready(self, value):
2738 obj = ObjectIdentifier()
2739 self.assertFalse(obj.ready)
2742 pprint(obj, big_blobs=True, with_decode_path=True)
2743 with self.assertRaises(ObjNotReady) as err:
2746 with self.assertRaises(ObjNotReady) as err:
2748 obj = ObjectIdentifier(value)
2749 self.assertTrue(obj.ready)
2750 self.assertFalse(obj.ber_encoded)
2753 pprint(obj, big_blobs=True, with_decode_path=True)
2756 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2757 def test_comparison(self, value1, value2, tag1, tag2):
2758 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2759 obj1 = klass(value1)
2760 obj2 = klass(value2)
2761 self.assertEqual(obj1 == obj2, value1 == value2)
2762 self.assertEqual(obj1 != obj2, value1 != value2)
2763 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2764 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2765 obj1 = klass(value1, impl=tag1)
2766 obj2 = klass(value1, impl=tag2)
2767 self.assertEqual(obj1 == obj2, tag1 == tag2)
2768 self.assertEqual(obj1 != obj2, tag1 != tag2)
2770 @given(lists(oid_strategy()))
2771 def test_sorted_works(self, values):
2772 self.assertSequenceEqual(
2773 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2777 @given(data_strategy())
2778 def test_call(self, d):
2779 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2787 ) = d.draw(oid_values_strategy())
2788 obj_initial = klass(
2789 value=value_initial,
2792 default=default_initial,
2793 optional=optional_initial or False,
2794 _decoded=_decoded_initial,
2803 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2812 value_expected = default if value is None else value
2814 default_initial if value_expected is None
2817 self.assertEqual(obj, value_expected)
2818 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2819 self.assertEqual(obj.expl_tag, expl or expl_initial)
2822 default_initial if default is None else default,
2824 if obj.default is None:
2825 optional = optional_initial if optional is None else optional
2826 optional = False if optional is None else optional
2829 self.assertEqual(obj.optional, optional)
2831 @given(oid_values_strategy())
2832 def test_copy(self, values):
2833 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2850 for copy_func in copy_funcs:
2851 obj_copied = copy_func(obj)
2852 self.assert_copied_basic_fields(obj, obj_copied)
2853 self.assertEqual(obj._value, obj_copied._value)
2855 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2858 integers(min_value=1).map(tag_encode),
2860 def test_stripped(self, value, tag_impl):
2861 obj = ObjectIdentifier(value, impl=tag_impl)
2862 with self.assertRaises(NotEnoughData):
2863 obj.decode(obj.encode()[:-1])
2867 integers(min_value=1).map(tag_ctxc),
2869 def test_stripped_expl(self, value, tag_expl):
2870 obj = ObjectIdentifier(value, expl=tag_expl)
2871 with self.assertRaises(NotEnoughData):
2872 obj.decode(obj.encode()[:-1])
2875 integers(min_value=31),
2876 integers(min_value=0),
2879 def test_bad_tag(self, tag, offset, decode_path):
2880 with self.assertRaises(DecodeError) as err:
2881 ObjectIdentifier().decode(
2882 tag_encode(tag)[:-1],
2884 decode_path=decode_path,
2887 self.assertEqual(err.exception.offset, offset)
2888 self.assertEqual(err.exception.decode_path, decode_path)
2891 integers(min_value=128),
2892 integers(min_value=0),
2895 def test_bad_len(self, l, offset, decode_path):
2896 with self.assertRaises(DecodeError) as err:
2897 ObjectIdentifier().decode(
2898 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2900 decode_path=decode_path,
2903 self.assertEqual(err.exception.offset, offset)
2904 self.assertEqual(err.exception.decode_path, decode_path)
2906 def test_zero_oid(self):
2907 with self.assertRaises(NotEnoughData):
2908 ObjectIdentifier().decode(
2909 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2913 @given(oid_strategy())
2914 def test_unfinished_oid(self, value):
2915 assume(list(value)[-1] > 255)
2916 obj_encoded = ObjectIdentifier(value).encode()
2917 obj, _ = ObjectIdentifier().decode(obj_encoded)
2918 data = obj_encoded[obj.tlen + obj.llen:-1]
2920 ObjectIdentifier.tag_default,
2921 len_encode(len(data)),
2924 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2927 @given(integers(min_value=0))
2928 def test_invalid_short(self, value):
2929 with self.assertRaises(InvalidOID):
2930 ObjectIdentifier((value,))
2931 with self.assertRaises(InvalidOID):
2932 ObjectIdentifier("%d" % value)
2934 @given(integers(min_value=3), integers(min_value=0))
2935 def test_invalid_first_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(integers(min_value=0, max_value=1), integers(min_value=40))
2942 def test_invalid_second_arc(self, first_arc, second_arc):
2943 with self.assertRaises(InvalidOID):
2944 ObjectIdentifier((first_arc, second_arc))
2945 with self.assertRaises(InvalidOID):
2946 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2948 @given(text(alphabet=ascii_letters + ".", min_size=1))
2949 def test_junk(self, oid):
2950 with self.assertRaises(InvalidOID):
2951 ObjectIdentifier(oid)
2953 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2954 @given(oid_strategy())
2955 def test_validness(self, oid):
2956 obj = ObjectIdentifier(oid)
2957 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2960 pprint(obj, big_blobs=True, with_decode_path=True)
2962 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2964 oid_values_strategy(),
2966 integers(min_value=1).map(tag_ctxc),
2967 integers(min_value=0),
2971 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2972 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2973 _, _, _, default, optional, _decoded = values
2982 pprint(obj, big_blobs=True, with_decode_path=True)
2983 self.assertFalse(obj.expled)
2984 obj_encoded = obj.encode()
2985 self.assertEqual(encode2pass(obj), obj_encoded)
2986 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2987 obj_expled = obj(value, expl=tag_expl)
2988 self.assertTrue(obj_expled.expled)
2990 list(obj_expled.pps())
2991 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2992 obj_expled_encoded = obj_expled.encode()
2993 obj_expled_cer = encode_cer(obj_expled)
2994 self.assertNotEqual(obj_expled_cer, obj_encoded)
2995 self.assertSequenceEqual(
2996 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2999 ctx_copied = deepcopy(ctx_dummy)
3000 obj_decoded, tail = obj_expled.decode(
3001 obj_expled_encoded + tail_junk,
3005 self.assertDictEqual(ctx_copied, ctx_dummy)
3007 list(obj_decoded.pps())
3008 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3009 self.assertEqual(tail, tail_junk)
3010 self.assertEqual(obj_decoded, obj_expled)
3011 self.assertNotEqual(obj_decoded, obj)
3012 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
3013 self.assertEqual(tuple(obj_decoded), tuple(obj))
3014 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3015 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3016 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3018 obj_decoded.expl_llen,
3019 len(len_encode(len(obj_encoded))),
3021 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3022 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3025 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3027 self.assertEqual(obj_decoded.expl_offset, offset)
3028 assert_exceeding_data(
3030 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3034 evgens = list(obj_expled.decode_evgen(
3035 obj_expled_encoded + tail_junk,
3037 decode_path=decode_path,
3040 self.assertEqual(len(evgens), 1)
3041 _decode_path, obj, tail = evgens[0]
3042 self.assertSequenceEqual(tail, tail_junk)
3043 self.assertEqual(_decode_path, decode_path)
3044 self.assertEqual(obj, obj_decoded)
3045 self.assertEqual(obj.expl_offset, offset)
3050 oid_strategy().map(ObjectIdentifier),
3051 oid_strategy().map(ObjectIdentifier),
3053 def test_add(self, oid1, oid2):
3054 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3055 for oid_to_add in (oid2, tuple(oid2)):
3056 self.assertEqual(oid1 + oid_to_add, oid_expect)
3057 with self.assertRaises(InvalidValueType):
3060 def test_go_vectors_valid(self):
3061 for data, expect in (
3063 (b"\x55\x02", (2, 5, 2)),
3064 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3065 (b"\x81\x34\x03", (2, 100, 3)),
3068 ObjectIdentifier().decode(b"".join((
3069 ObjectIdentifier.tag_default,
3070 len_encode(len(data)),
3076 def test_go_vectors_invalid(self):
3077 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3078 with self.assertRaises(DecodeError):
3079 ObjectIdentifier().decode(b"".join((
3080 Integer.tag_default,
3081 len_encode(len(data)),
3085 def test_go_non_minimal_encoding(self):
3086 with self.assertRaises(DecodeError):
3087 ObjectIdentifier().decode(hexdec("060a2a80864886f70d01010b"))
3089 def test_x690_vector(self):
3091 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3092 ObjectIdentifier((2, 999, 3)),
3095 def test_nonnormalized_first_arc(self):
3097 ObjectIdentifier.tag_default +
3100 ObjectIdentifier((1, 0)).encode()[-1:]
3102 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3103 self.assertTrue(obj.ber_encoded)
3104 self.assertTrue(obj.bered)
3106 self.assertTrue(obj.ber_encoded)
3107 self.assertTrue(obj.bered)
3108 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3109 ObjectIdentifier().decode(tampered)
3111 @given(data_strategy())
3112 def test_negative_arcs(self, d):
3113 oid = list(d.draw(oid_strategy()))
3116 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3118 if oid[idx - 1] == 0:
3120 with self.assertRaises(InvalidOID):
3121 ObjectIdentifier(tuple(oid))
3122 with self.assertRaises(InvalidOID):
3123 ObjectIdentifier(".".join(str(i) for i in oid))
3125 @given(data_strategy())
3126 def test_plused_arcs(self, d):
3127 oid = [str(arc) for arc in d.draw(oid_strategy())]
3128 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3129 oid[idx - 1] = "+" + oid[idx - 1]
3130 with self.assertRaises(InvalidOID):
3131 ObjectIdentifier(".".join(str(i) for i in oid))
3133 @given(data_strategy())
3134 def test_nonnormalized_arcs(self, d):
3135 arcs = d.draw(lists(
3136 integers(min_value=0, max_value=100),
3140 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3141 _, _, lv = tag_strip(dered)
3142 _, _, v = len_decode(lv)
3143 v_no_first_arc = v[1:]
3144 idx_for_tamper = d.draw(integers(
3146 max_value=len(v_no_first_arc) - 1,
3148 tampered = list(bytearray(v_no_first_arc))
3149 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3150 tampered.insert(idx_for_tamper, 0x80)
3151 tampered = bytes(bytearray(tampered))
3153 ObjectIdentifier.tag_default +
3154 len_encode(len(tampered)) +
3157 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3158 self.assertTrue(obj.ber_encoded)
3159 self.assertTrue(obj.bered)
3161 self.assertTrue(obj.ber_encoded)
3162 self.assertTrue(obj.bered)
3163 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3164 ObjectIdentifier().decode(tampered)
3168 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3170 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3171 values = list(draw(sets(
3173 min_size=len(schema),
3174 max_size=len(schema),
3176 schema = list(zip(schema, values))
3177 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3181 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3183 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3184 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3185 optional = draw(one_of(none(), booleans()))
3187 draw(integers(min_value=0)),
3188 draw(integers(min_value=0)),
3189 draw(integers(min_value=0)),
3191 return (schema, value, impl, expl, default, optional, _decoded)
3194 class TestEnumerated(CommonMixin, TestCase):
3195 class EWhatever(Enumerated):
3196 schema = (("whatever", 0),)
3198 base_klass = EWhatever
3200 def test_schema_required(self):
3201 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3204 def test_invalid_value_type(self):
3205 with self.assertRaises(InvalidValueType) as err:
3206 self.base_klass((1, 2))
3209 @given(sets(text_letters(), min_size=2))
3210 def test_unknown_name(self, schema_input):
3211 missing = schema_input.pop()
3213 class E(Enumerated):
3214 schema = [(n, 123) for n in schema_input]
3215 with self.assertRaises(ObjUnknown) as err:
3220 sets(text_letters(), min_size=2),
3221 sets(integers(), min_size=2),
3223 def test_unknown_value(self, schema_input, values_input):
3225 missing_value = values_input.pop()
3226 _input = list(zip(schema_input, values_input))
3228 class E(Enumerated):
3230 with self.assertRaises(DecodeError) as err:
3235 def test_optional(self, optional):
3236 obj = self.base_klass(default="whatever", optional=optional)
3237 self.assertTrue(obj.optional)
3239 def test_ready(self):
3240 obj = self.base_klass()
3241 self.assertFalse(obj.ready)
3244 pprint(obj, big_blobs=True, with_decode_path=True)
3245 with self.assertRaises(ObjNotReady) as err:
3248 obj = self.base_klass("whatever")
3249 self.assertTrue(obj.ready)
3252 pprint(obj, big_blobs=True, with_decode_path=True)
3254 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3255 def test_comparison(self, value1, value2, tag1, tag2):
3256 class E(Enumerated):
3258 ("whatever0", value1),
3259 ("whatever1", value2),
3262 class EInherited(E):
3264 for klass in (E, EInherited):
3265 obj1 = klass(value1)
3266 obj2 = klass(value2)
3267 self.assertEqual(obj1 == obj2, value1 == value2)
3268 self.assertEqual(obj1 != obj2, value1 != value2)
3269 self.assertEqual(obj1 == int(obj2), value1 == value2)
3270 obj1 = klass(value1, impl=tag1)
3271 obj2 = klass(value1, impl=tag2)
3272 self.assertEqual(obj1 == obj2, tag1 == tag2)
3273 self.assertEqual(obj1 != obj2, tag1 != tag2)
3275 @given(data_strategy())
3276 def test_call(self, d):
3285 ) = d.draw(enumerated_values_strategy())
3287 class E(Enumerated):
3288 schema = schema_initial
3290 value=value_initial,
3293 default=default_initial,
3294 optional=optional_initial or False,
3295 _decoded=_decoded_initial,
3305 ) = d.draw(enumerated_values_strategy(
3306 schema=schema_initial,
3307 do_expl=impl_initial is None,
3317 value_expected = default if value is None else value
3319 default_initial if value_expected is None
3324 dict(schema_initial).get(value_expected, value_expected),
3326 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3327 self.assertEqual(obj.expl_tag, expl or expl_initial)
3330 default_initial if default is None else default,
3332 if obj.default is None:
3333 optional = optional_initial if optional is None else optional
3334 optional = False if optional is None else optional
3337 self.assertEqual(obj.optional, optional)
3338 self.assertEqual(obj.specs, dict(schema_initial))
3340 @given(enumerated_values_strategy())
3341 def test_copy(self, values):
3342 schema_input, value, impl, expl, default, optional, _decoded = values
3344 class E(Enumerated):
3345 schema = schema_input
3355 for copy_func in copy_funcs:
3356 obj_copied = copy_func(obj)
3357 self.assert_copied_basic_fields(obj, obj_copied)
3358 self.assertEqual(obj.specs, obj_copied.specs)
3360 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3361 @given(data_strategy())
3362 def test_symmetric(self, d):
3363 schema_input, _, _, _, default, optional, _decoded = d.draw(
3364 enumerated_values_strategy(),
3366 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3367 offset = d.draw(integers(min_value=0))
3368 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3369 tail_junk = d.draw(binary(max_size=5))
3370 decode_path = d.draw(decode_path_strat)
3372 class E(Enumerated):
3373 schema = schema_input
3382 pprint(obj, big_blobs=True, with_decode_path=True)
3383 self.assertFalse(obj.expled)
3384 obj_encoded = obj.encode()
3385 self.assertEqual(encode2pass(obj), obj_encoded)
3386 obj_expled = obj(value, expl=tag_expl)
3387 self.assertTrue(obj_expled.expled)
3389 list(obj_expled.pps())
3390 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3391 obj_expled_encoded = obj_expled.encode()
3392 ctx_copied = deepcopy(ctx_dummy)
3393 obj_decoded, tail = obj_expled.decode(
3394 obj_expled_encoded + tail_junk,
3398 self.assertDictEqual(ctx_copied, ctx_dummy)
3400 list(obj_decoded.pps())
3401 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3402 self.assertEqual(tail, tail_junk)
3403 self.assertEqual(obj_decoded, obj_expled)
3404 self.assertNotEqual(obj_decoded, obj)
3405 self.assertEqual(int(obj_decoded), int(obj_expled))
3406 self.assertEqual(int(obj_decoded), int(obj))
3407 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3408 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3409 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3411 obj_decoded.expl_llen,
3412 len(len_encode(len(obj_encoded))),
3414 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3415 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3418 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3420 self.assertEqual(obj_decoded.expl_offset, offset)
3421 assert_exceeding_data(
3423 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3427 evgens = list(obj_expled.decode_evgen(
3428 obj_expled_encoded + tail_junk,
3430 decode_path=decode_path,
3433 self.assertEqual(len(evgens), 1)
3434 _decode_path, obj, tail = evgens[0]
3435 self.assertSequenceEqual(tail, tail_junk)
3436 self.assertEqual(_decode_path, decode_path)
3437 self.assertEqual(obj, obj_decoded)
3438 self.assertEqual(obj.expl_offset, offset)
3444 def string_values_strategy(draw, alphabet, do_expl=False):
3445 bound_min, bound_max = sorted(draw(sets(
3446 integers(min_value=0, max_value=1 << 7),
3450 value = draw(one_of(
3452 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3454 default = draw(one_of(
3456 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3459 if draw(booleans()):
3460 bounds = (bound_min, bound_max)
3464 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3466 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3467 optional = draw(one_of(none(), booleans()))
3469 draw(integers(min_value=0)),
3470 draw(integers(min_value=0)),
3471 draw(integers(min_value=0)),
3473 return (value, bounds, impl, expl, default, optional, _decoded)
3476 class StringMixin(object):
3477 def test_invalid_value_type(self):
3478 with self.assertRaises(InvalidValueType) as err:
3479 self.base_klass((1, 2))
3482 def text_alphabet(self):
3483 return "".join(six_unichr(c) for c in six_xrange(256))
3486 def test_optional(self, optional):
3487 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3488 self.assertTrue(obj.optional)
3490 @given(data_strategy())
3491 def test_ready(self, d):
3492 obj = self.base_klass()
3493 self.assertFalse(obj.ready)
3496 pprint(obj, big_blobs=True, with_decode_path=True)
3498 with self.assertRaises(ObjNotReady) as err:
3501 with self.assertRaises(ObjNotReady) as err:
3503 value = d.draw(text(alphabet=self.text_alphabet()))
3504 obj = self.base_klass(value)
3505 self.assertTrue(obj.ready)
3508 pprint(obj, big_blobs=True, with_decode_path=True)
3511 @given(data_strategy())
3512 def test_comparison(self, d):
3513 value1 = d.draw(text(alphabet=self.text_alphabet()))
3514 value2 = d.draw(text(alphabet=self.text_alphabet()))
3515 tag1 = d.draw(binary(min_size=1))
3516 tag2 = d.draw(binary(min_size=1))
3517 obj1 = self.base_klass(value1)
3518 obj2 = self.base_klass(value2)
3519 self.assertEqual(obj1 == obj2, value1 == value2)
3520 self.assertEqual(obj1 != obj2, value1 != value2)
3521 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3522 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3523 obj1 = self.base_klass(value1, impl=tag1)
3524 obj2 = self.base_klass(value1, impl=tag2)
3525 self.assertEqual(obj1 == obj2, tag1 == tag2)
3526 self.assertEqual(obj1 != obj2, tag1 != tag2)
3528 @given(data_strategy())
3529 def test_bounds_satisfied(self, d):
3530 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3531 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3532 value = d.draw(text(
3533 alphabet=self.text_alphabet(),
3537 self.base_klass(value=value, bounds=(bound_min, bound_max))
3539 @given(data_strategy())
3540 def test_bounds_unsatisfied(self, d):
3541 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3542 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3543 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3544 with self.assertRaises(BoundsError) as err:
3545 self.base_klass(value=value, bounds=(bound_min, bound_max))
3547 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3548 self.base_klass(bounds=(bound_min, bound_max)).decode(
3549 self.base_klass(value).encode()
3552 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3553 self.base_klass(bounds=(bound_min, bound_max)).decode(
3554 encode2pass(self.base_klass(value))
3556 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3557 with self.assertRaises(BoundsError) as err:
3558 self.base_klass(value=value, bounds=(bound_min, bound_max))
3560 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3561 self.base_klass(bounds=(bound_min, bound_max)).decode(
3562 self.base_klass(value).encode()
3565 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3566 self.base_klass(bounds=(bound_min, bound_max)).decode(
3567 encode2pass(self.base_klass(value))
3570 @given(data_strategy())
3571 def test_call(self, d):
3580 ) = d.draw(string_values_strategy(self.text_alphabet()))
3581 obj_initial = self.base_klass(
3587 optional_initial or False,
3598 ) = d.draw(string_values_strategy(
3599 self.text_alphabet(),
3600 do_expl=impl_initial is None,
3602 if (default is None) and (obj_initial.default is not None):
3605 (bounds is None) and
3606 (value is not None) and
3607 (bounds_initial is not None) and
3608 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3612 (bounds is None) and
3613 (default is not None) and
3614 (bounds_initial is not None) and
3615 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3618 obj = obj_initial(value, bounds, impl, expl, default, optional)
3620 value_expected = default if value is None else value
3622 default_initial if value_expected is None
3625 self.assertEqual(obj, value_expected)
3626 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3627 self.assertEqual(obj.expl_tag, expl or expl_initial)
3630 default_initial if default is None else default,
3632 if obj.default is None:
3633 optional = optional_initial if optional is None else optional
3634 optional = False if optional is None else optional
3637 self.assertEqual(obj.optional, optional)
3639 (obj._bound_min, obj._bound_max),
3640 bounds or bounds_initial or (0, float("+inf")),
3643 @given(data_strategy())
3644 def test_copy(self, d):
3645 values = d.draw(string_values_strategy(self.text_alphabet()))
3646 obj = self.base_klass(*values)
3647 for copy_func in copy_funcs:
3648 obj_copied = copy_func(obj)
3649 self.assert_copied_basic_fields(obj, obj_copied)
3650 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3651 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3652 self.assertEqual(obj._value, obj_copied._value)
3654 @given(data_strategy())
3655 def test_stripped(self, d):
3656 value = d.draw(text(alphabet=self.text_alphabet()))
3657 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3658 obj = self.base_klass(value, impl=tag_impl)
3659 with self.assertRaises(NotEnoughData):
3660 obj.decode(obj.encode()[:-1])
3662 @given(data_strategy())
3663 def test_stripped_expl(self, d):
3664 value = d.draw(text(alphabet=self.text_alphabet()))
3665 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3666 obj = self.base_klass(value, expl=tag_expl)
3667 with self.assertRaises(NotEnoughData):
3668 obj.decode(obj.encode()[:-1])
3671 integers(min_value=31),
3672 integers(min_value=0),
3675 def test_bad_tag(self, tag, offset, decode_path):
3676 with self.assertRaises(DecodeError) as err:
3677 self.base_klass().decode(
3678 tag_encode(tag)[:-1],
3680 decode_path=decode_path,
3683 self.assertEqual(err.exception.offset, offset)
3684 self.assertEqual(err.exception.decode_path, decode_path)
3687 integers(min_value=128),
3688 integers(min_value=0),
3691 def test_bad_len(self, l, offset, decode_path):
3692 with self.assertRaises(DecodeError) as err:
3693 self.base_klass().decode(
3694 self.base_klass.tag_default + len_encode(l)[:-1],
3696 decode_path=decode_path,
3699 self.assertEqual(err.exception.offset, offset)
3700 self.assertEqual(err.exception.decode_path, decode_path)
3703 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3704 integers(min_value=0),
3707 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3708 value, bound_min = list(sorted(ints))
3710 class String(self.base_klass):
3711 # Multiply this value by four, to satisfy UTF-32 bounds
3712 # (4 bytes per character) validation
3713 bounds = (bound_min * 4, bound_min * 4)
3714 with self.assertRaises(DecodeError) as err:
3716 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3718 decode_path=decode_path,
3721 self.assertEqual(err.exception.offset, offset)
3722 self.assertEqual(err.exception.decode_path, decode_path)
3724 @given(data_strategy())
3725 def test_symmetric(self, d):
3726 values = d.draw(string_values_strategy(self.text_alphabet()))
3727 value = d.draw(text(alphabet=self.text_alphabet()))
3728 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3729 offset = d.draw(integers(min_value=0))
3730 tail_junk = d.draw(binary(max_size=5))
3731 decode_path = d.draw(decode_path_strat)
3732 _, _, _, _, default, optional, _decoded = values
3733 obj = self.base_klass(
3741 pprint(obj, big_blobs=True, with_decode_path=True)
3742 self.assertFalse(obj.expled)
3743 obj_encoded = obj.encode()
3744 self.assertEqual(encode2pass(obj), obj_encoded)
3745 obj_expled = obj(value, expl=tag_expl)
3746 self.assertTrue(obj_expled.expled)
3748 list(obj_expled.pps())
3749 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3750 obj_expled_encoded = obj_expled.encode()
3751 ctx_copied = deepcopy(ctx_dummy)
3752 obj_decoded, tail = obj_expled.decode(
3753 obj_expled_encoded + tail_junk,
3757 self.assertDictEqual(ctx_copied, ctx_dummy)
3759 list(obj_decoded.pps())
3760 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3761 self.assertEqual(tail, tail_junk)
3762 self.assertEqual(obj_decoded, obj_expled)
3763 self.assertNotEqual(obj_decoded, obj)
3764 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3765 self.assertEqual(bytes(obj_decoded), bytes(obj))
3766 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3767 self.assertEqual(text_type(obj_decoded), text_type(obj))
3768 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3769 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3770 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3772 obj_decoded.expl_llen,
3773 len(len_encode(len(obj_encoded))),
3775 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3776 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3779 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3781 self.assertEqual(obj_decoded.expl_offset, offset)
3782 assert_exceeding_data(
3784 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3788 evgens = list(obj_expled.decode_evgen(
3789 obj_expled_encoded + tail_junk,
3791 decode_path=decode_path,
3794 self.assertEqual(len(evgens), 1)
3795 _decode_path, obj, tail = evgens[0]
3796 self.assertSequenceEqual(tail, tail_junk)
3797 self.assertEqual(_decode_path, decode_path)
3798 if not getattr(self, "evgen_mode_skip_value", True):
3799 self.assertEqual(obj, obj_decoded)
3800 self.assertEqual(obj.expl_offset, offset)
3805 cyrillic_letters = text(
3806 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3812 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3813 base_klass = UTF8String
3815 @given(cyrillic_letters)
3816 def test_byte_per_primitive(self, chars):
3818 char_raw = char.encode("utf-8")
3819 encoded = b"".join((
3820 self.base_klass().tag_constructed,
3822 OctetString(char_raw[:1]).encode(),
3823 OctetString(char_raw[1:2]).encode(),
3827 self.base_klass().decod(encoded, ctx={"bered": True}),
3832 class UnicodeDecodeErrorMixin(object):
3833 @given(cyrillic_letters)
3834 def test_unicode_decode_error(self, cyrillic_text):
3835 with self.assertRaises(DecodeError):
3836 self.base_klass(cyrillic_text)
3839 class TestNumericString(StringMixin, CommonMixin, TestCase):
3840 base_klass = NumericString
3842 def text_alphabet(self):
3845 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3846 def test_non_numeric(self, non_numeric_text):
3847 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3848 self.base_klass(non_numeric_text)
3851 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3852 integers(min_value=0),
3855 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3856 value, bound_min = list(sorted(ints))
3858 class String(self.base_klass):
3859 bounds = (bound_min, bound_min)
3860 with self.assertRaises(DecodeError) as err:
3862 self.base_klass(b"1" * value).encode(),
3864 decode_path=decode_path,
3867 self.assertEqual(err.exception.offset, offset)
3868 self.assertEqual(err.exception.decode_path, decode_path)
3870 def test_byte_per_primitive(self):
3871 encoded = b"".join((
3872 self.base_klass().tag_constructed,
3874 OctetString(b"1").encode(),
3875 OctetString(b"2").encode(),
3879 self.base_klass().decod(encoded, ctx={"bered": True}),
3884 class TestPrintableString(
3885 UnicodeDecodeErrorMixin,
3890 base_klass = PrintableString
3892 def text_alphabet(self):
3893 return ascii_letters + digits + " '()+,-./:=?"
3895 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3896 def test_non_printable(self, non_printable_text):
3897 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3898 self.base_klass(non_printable_text)
3901 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3902 integers(min_value=0),
3905 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3906 value, bound_min = list(sorted(ints))
3908 class String(self.base_klass):
3909 bounds = (bound_min, bound_min)
3910 with self.assertRaises(DecodeError) as err:
3912 self.base_klass(b"1" * value).encode(),
3914 decode_path=decode_path,
3917 self.assertEqual(err.exception.offset, offset)
3918 self.assertEqual(err.exception.decode_path, decode_path)
3920 def test_allowable_invalid_chars(self):
3922 ("*", {"allow_asterisk": True}),
3923 ("&", {"allow_ampersand": True}),
3924 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3927 obj = self.base_klass(s)
3928 for prop in kwargs.keys():
3929 self.assertFalse(getattr(obj, prop))
3931 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3933 self.base_klass(s, **kwargs)
3934 klass = self.base_klass(**kwargs)
3936 for prop in kwargs.keys():
3937 self.assertTrue(getattr(obj, prop))
3940 for prop in kwargs.keys():
3941 self.assertTrue(getattr(obj, prop))
3944 class TestTeletexString(
3945 UnicodeDecodeErrorMixin,
3950 base_klass = TeletexString
3953 class TestVideotexString(
3954 UnicodeDecodeErrorMixin,
3959 base_klass = VideotexString
3962 class TestIA5String(
3963 UnicodeDecodeErrorMixin,
3968 base_klass = IA5String
3970 def text_alphabet(self):
3971 return "".join(six_unichr(c) for c in six_xrange(128))
3973 @given(integers(min_value=128, max_value=255))
3974 def test_alphabet_bad(self, code):
3975 with self.assertRaises(DecodeError):
3976 self.base_klass().decod(
3977 self.base_klass.tag_default +
3979 bytes(bytearray([code])),
3983 class TestGraphicString(
3984 UnicodeDecodeErrorMixin,
3989 base_klass = GraphicString
3992 class TestVisibleString(
3993 UnicodeDecodeErrorMixin,
3998 base_klass = VisibleString
4000 def text_alphabet(self):
4001 return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
4003 def test_x690_vector(self):
4004 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
4005 self.assertSequenceEqual(tail, b"")
4006 self.assertEqual(str(obj), "Jones")
4007 self.assertFalse(obj.ber_encoded)
4008 self.assertFalse(obj.lenindef)
4009 self.assertFalse(obj.bered)
4011 obj, tail = VisibleString().decode(
4012 hexdec("3A0904034A6F6E04026573"),
4013 ctx={"bered": True},
4015 self.assertSequenceEqual(tail, b"")
4016 self.assertEqual(str(obj), "Jones")
4017 self.assertTrue(obj.ber_encoded)
4018 self.assertFalse(obj.lenindef)
4019 self.assertTrue(obj.bered)
4021 self.assertTrue(obj.ber_encoded)
4022 self.assertFalse(obj.lenindef)
4023 self.assertTrue(obj.bered)
4025 obj, tail = VisibleString().decode(
4026 hexdec("3A8004034A6F6E040265730000"),
4027 ctx={"bered": True},
4029 self.assertSequenceEqual(tail, b"")
4030 self.assertEqual(str(obj), "Jones")
4031 self.assertTrue(obj.ber_encoded)
4032 self.assertTrue(obj.lenindef)
4033 self.assertTrue(obj.bered)
4035 self.assertTrue(obj.ber_encoded)
4036 self.assertTrue(obj.lenindef)
4037 self.assertTrue(obj.bered)
4040 integers(min_value=0, max_value=ord(" ") - 1),
4041 integers(min_value=ord("~") + 1, max_value=255),
4043 def test_alphabet_bad(self, code):
4044 with self.assertRaises(DecodeError):
4045 self.base_klass().decod(
4046 self.base_klass.tag_default +
4048 bytes(bytearray([code])),
4052 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
4053 integers(min_value=0),
4056 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
4057 value, bound_min = list(sorted(ints))
4059 class String(self.base_klass):
4060 bounds = (bound_min, bound_min)
4061 with self.assertRaises(DecodeError) as err:
4063 self.base_klass(b"1" * value).encode(),
4065 decode_path=decode_path,
4068 self.assertEqual(err.exception.offset, offset)
4069 self.assertEqual(err.exception.decode_path, decode_path)
4072 class TestGeneralString(
4073 UnicodeDecodeErrorMixin,
4078 base_klass = GeneralString
4081 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4082 base_klass = UniversalString
4085 class TestBMPString(StringMixin, CommonMixin, TestCase):
4086 base_klass = BMPString
4090 def generalized_time_values_strategy(
4098 if draw(booleans()):
4099 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4101 value = value.replace(microsecond=0)
4103 if draw(booleans()):
4104 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4106 default = default.replace(microsecond=0)
4110 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4112 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4113 optional = draw(one_of(none(), booleans()))
4115 draw(integers(min_value=0)),
4116 draw(integers(min_value=0)),
4117 draw(integers(min_value=0)),
4119 return (value, impl, expl, default, optional, _decoded)
4122 class TimeMixin(object):
4123 def test_invalid_value_type(self):
4124 with self.assertRaises(InvalidValueType) as err:
4125 self.base_klass(datetime.now().timetuple())
4128 @given(data_strategy())
4129 def test_optional(self, d):
4130 default = d.draw(datetimes(
4131 min_value=self.min_datetime,
4132 max_value=self.max_datetime,
4134 optional = d.draw(booleans())
4135 obj = self.base_klass(default=default, optional=optional)
4136 self.assertTrue(obj.optional)
4138 @given(data_strategy())
4139 def test_ready(self, d):
4140 obj = self.base_klass()
4141 self.assertFalse(obj.ready)
4144 pprint(obj, big_blobs=True, with_decode_path=True)
4145 with self.assertRaises(ObjNotReady) as err:
4148 with self.assertRaises(ObjNotReady) as err:
4150 value = d.draw(datetimes(
4151 min_value=self.min_datetime,
4152 max_value=self.max_datetime,
4154 obj = self.base_klass(value)
4155 self.assertTrue(obj.ready)
4158 pprint(obj, big_blobs=True, with_decode_path=True)
4160 @given(data_strategy())
4161 def test_comparison(self, d):
4162 value1 = d.draw(datetimes(
4163 min_value=self.min_datetime,
4164 max_value=self.max_datetime,
4166 value2 = d.draw(datetimes(
4167 min_value=self.min_datetime,
4168 max_value=self.max_datetime,
4170 tag1 = d.draw(binary(min_size=1))
4171 tag2 = d.draw(binary(min_size=1))
4173 value1 = value1.replace(microsecond=0)
4174 value2 = value2.replace(microsecond=0)
4175 obj1 = self.base_klass(value1)
4176 obj2 = self.base_klass(value2)
4177 self.assertEqual(obj1 == obj2, value1 == value2)
4178 self.assertEqual(obj1 != obj2, value1 != value2)
4179 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4180 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4181 obj1 = self.base_klass(value1, impl=tag1)
4182 obj2 = self.base_klass(value1, impl=tag2)
4183 self.assertEqual(obj1 == obj2, tag1 == tag2)
4184 self.assertEqual(obj1 != obj2, tag1 != tag2)
4186 @given(data_strategy())
4187 def test_call(self, d):
4195 ) = d.draw(generalized_time_values_strategy(
4196 min_datetime=self.min_datetime,
4197 max_datetime=self.max_datetime,
4198 omit_ms=self.omit_ms,
4200 obj_initial = self.base_klass(
4201 value=value_initial,
4204 default=default_initial,
4205 optional=optional_initial or False,
4206 _decoded=_decoded_initial,
4215 ) = d.draw(generalized_time_values_strategy(
4216 min_datetime=self.min_datetime,
4217 max_datetime=self.max_datetime,
4218 omit_ms=self.omit_ms,
4219 do_expl=impl_initial is None,
4229 value_expected = default if value is None else value
4231 default_initial if value_expected is None
4234 self.assertEqual(obj, value_expected)
4235 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4236 self.assertEqual(obj.expl_tag, expl or expl_initial)
4239 default_initial if default is None else default,
4241 if obj.default is None:
4242 optional = optional_initial if optional is None else optional
4243 optional = False if optional is None else optional
4246 self.assertEqual(obj.optional, optional)
4248 @given(data_strategy())
4249 def test_copy(self, d):
4250 values = d.draw(generalized_time_values_strategy(
4251 min_datetime=self.min_datetime,
4252 max_datetime=self.max_datetime,
4254 obj = self.base_klass(*values)
4255 for copy_func in copy_funcs:
4256 obj_copied = copy_func(obj)
4257 self.assert_copied_basic_fields(obj, obj_copied)
4258 self.assertEqual(obj._value, obj_copied._value)
4260 @given(data_strategy())
4261 def test_stripped(self, d):
4262 value = d.draw(datetimes(
4263 min_value=self.min_datetime,
4264 max_value=self.max_datetime,
4266 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4267 obj = self.base_klass(value, impl=tag_impl)
4268 with self.assertRaises(NotEnoughData):
4269 obj.decode(obj.encode()[:-1])
4271 @given(data_strategy())
4272 def test_stripped_expl(self, d):
4273 value = d.draw(datetimes(
4274 min_value=self.min_datetime,
4275 max_value=self.max_datetime,
4277 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4278 obj = self.base_klass(value, expl=tag_expl)
4279 with self.assertRaises(NotEnoughData):
4280 obj.decode(obj.encode()[:-1])
4282 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4283 @given(data_strategy())
4284 def test_symmetric(self, d):
4285 values = d.draw(generalized_time_values_strategy(
4286 min_datetime=self.min_datetime,
4287 max_datetime=self.max_datetime,
4289 value = d.draw(datetimes(
4290 min_value=self.min_datetime,
4291 max_value=self.max_datetime,
4293 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4294 offset = d.draw(integers(min_value=0))
4295 tail_junk = d.draw(binary(max_size=5))
4296 _, _, _, default, optional, _decoded = values
4297 obj = self.base_klass(
4305 pprint(obj, big_blobs=True, with_decode_path=True)
4306 self.assertFalse(obj.expled)
4307 obj_encoded = obj.encode()
4308 self.assertEqual(encode2pass(obj), obj_encoded)
4309 self.additional_symmetric_check(value, obj_encoded)
4310 obj_expled = obj(value, expl=tag_expl)
4311 self.assertTrue(obj_expled.expled)
4313 list(obj_expled.pps())
4314 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4315 obj_expled_encoded = obj_expled.encode()
4316 ctx_copied = deepcopy(ctx_dummy)
4317 obj_decoded, tail = obj_expled.decode(
4318 obj_expled_encoded + tail_junk,
4322 self.assertDictEqual(ctx_copied, ctx_dummy)
4324 list(obj_decoded.pps())
4325 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4326 self.assertEqual(tail, tail_junk)
4327 self.assertEqual(obj_decoded, obj_expled)
4328 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4329 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4330 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4331 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4332 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4334 obj_decoded.expl_llen,
4335 len(len_encode(len(obj_encoded))),
4337 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4338 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4341 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4343 self.assertEqual(obj_decoded.expl_offset, offset)
4344 assert_exceeding_data(
4346 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4351 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4352 base_klass = GeneralizedTime
4354 min_datetime = datetime(1900, 1, 1)
4355 max_datetime = datetime(9999, 12, 31)
4356 evgen_mode_skip_value = False
4358 def additional_symmetric_check(self, value, obj_encoded):
4359 if value.microsecond > 0:
4360 self.assertFalse(obj_encoded.endswith(b"0Z"))
4362 def test_repr_not_ready(self):
4363 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4364 repr(GeneralizedTime())
4366 def test_x690_vector_valid(self):
4370 b"19920722132100.3Z",
4372 GeneralizedTime(data)
4374 def test_x690_vector_invalid(self):
4377 b"19920622123421.0Z",
4378 b"19920722132100.30Z",
4380 with self.assertRaises(DecodeError) as err:
4381 GeneralizedTime(data)
4384 def test_go_vectors_invalid(self):
4396 b"-20100102030410Z",
4397 b"2010-0102030410Z",
4398 b"2010-0002030410Z",
4399 b"201001-02030410Z",
4400 b"20100102-030410Z",
4401 b"2010010203-0410Z",
4402 b"201001020304-10Z",
4403 # These ones are INVALID in *DER*, but accepted
4404 # by Go's encoding/asn1
4405 b"20100102030405+0607",
4406 b"20100102030405-0607",
4408 with self.assertRaises(DecodeError) as err:
4409 GeneralizedTime(data)
4412 def test_go_vectors_valid(self):
4414 GeneralizedTime(b"20100102030405Z").todatetime(),
4415 datetime(2010, 1, 2, 3, 4, 5, 0),
4418 def test_go_vectors_valid_ber(self):
4420 b"20100102030405+0607",
4421 b"20100102030405-0607",
4423 GeneralizedTime(data, ctx={"bered": True})
4425 def test_utc_offsets(self):
4426 """Some know equal UTC offsets
4429 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4433 "200101011130-0700",
4434 "200101011500-03:30",
4437 self.assertEqual(dts[0], dts[1])
4438 self.assertEqual(dts[0], dts[2])
4439 self.assertEqual(dts[0], dts[3])
4441 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4442 @given(data_strategy())
4443 def test_valid_ber(self, d):
4444 min_year = 1901 if PY2 else 2
4445 year = d.draw(integers(min_value=min_year, max_value=9999))
4446 month = d.draw(integers(min_value=1, max_value=12))
4447 day = d.draw(integers(min_value=1, max_value=28))
4448 hours = d.draw(integers(min_value=0, max_value=23))
4449 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4450 dt = datetime(year, month, day, hours)
4451 fractions_sign = d.draw(sampled_from(" ,."))
4453 if fractions_sign != " ":
4454 fractions = random()
4455 if d.draw(booleans()):
4456 minutes = d.draw(integers(min_value=0, max_value=59))
4457 data += "%02d" % minutes
4458 dt += timedelta(seconds=60 * minutes)
4459 if d.draw(booleans()):
4460 seconds = d.draw(integers(min_value=0, max_value=59))
4461 data += "%02d" % seconds
4462 dt += timedelta(seconds=seconds)
4463 if fractions is not None:
4464 dt += timedelta(microseconds=10**6 * fractions)
4465 elif fractions is not None:
4466 dt += timedelta(seconds=60 * fractions)
4467 elif fractions is not None:
4468 dt += timedelta(seconds=3600 * fractions)
4469 if fractions is not None:
4470 data += fractions_sign + str(fractions)[2:]
4471 if d.draw(booleans()):
4473 elif d.draw(booleans()):
4474 offset_hour = d.draw(integers(min_value=0, max_value=13))
4476 if d.draw(booleans()):
4481 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4482 data += "%02d" % offset_hour
4483 minutes_separator = d.draw(sampled_from((None, "", ":")))
4484 if minutes_separator is not None:
4485 offset_minute = d.draw(integers(min_value=0, max_value=59))
4486 dt -= timedelta(seconds=sign * 60 * offset_minute)
4487 data += "%s%02d" % (minutes_separator, offset_minute)
4488 data = data.encode("ascii")
4489 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4491 GeneralizedTime().decod(data_der)
4496 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4499 mktime(obj.todatetime().timetuple()),
4500 mktime(dt.timetuple()),
4504 obj.todatetime().timestamp()
4508 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4509 self.assertEqual(obj.ber_encoded, not dered)
4510 self.assertEqual(obj.bered, not dered)
4511 self.assertEqual(obj.ber_raw, None if dered else data)
4512 self.assertEqual(obj.encode() == data_der, dered)
4517 def test_invalid_ber(self):
4519 # "00010203040506.07",
4520 "-0010203040506.07",
4521 "0001-203040506.07",
4522 "000102-3040506.07",
4523 "00010203-40506.07",
4524 "0001020304-506.07",
4525 "000102030405-6.07",
4526 "00010203040506.-7",
4527 "+0010203040506.07",
4528 "0001+203040506.07",
4529 "000102+3040506.07",
4530 "00010203+40506.07",
4531 "0001020304+506.07",
4532 "000102030405+6.07",
4533 "00010203040506.+7",
4534 " 0010203040506.07",
4535 "0001 203040506.07",
4536 "000102 3040506.07",
4537 "00010203 40506.07",
4538 "0001020304 506.07",
4539 "000102030405 6.07",
4540 "00010203040506. 7",
4541 "001 0203040506.07",
4542 "00012 03040506.07",
4543 "0001023 040506.07",
4544 "000102034 0506.07",
4545 "00010203045 06.07",
4546 "0001020304056 .07",
4547 "00010203040506.7 ",
4627 "00010203040506.07+15",
4628 "00010203040506.07-15",
4629 "00010203040506.07+14:60",
4630 "00010203040506.07+1460",
4631 "00010203040506.07-1460",
4632 "00010203040506.07+00:60",
4633 "00010203040506.07-00:60",
4635 "00010203040506+15",
4636 "00010203040506-15",
4637 "00010203040506+14:60",
4638 "00010203040506+1460",
4639 "00010203040506-1460",
4640 "00010203040506+00:60",
4641 "00010203040506-00:60",
4650 with self.assertRaises(DecodeError):
4651 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4652 data = data.replace(".", ",")
4653 with self.assertRaises(DecodeError):
4654 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4658 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4659 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4661 binary(min_size=1, max_size=1),
4663 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4664 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4667 def test_junk(self, part0, part1, part2):
4668 junk = part0 + part1 + part2
4669 assume(not (set(junk) <= set(digits.encode("ascii"))))
4670 with self.assertRaises(DecodeError):
4671 GeneralizedTime().decode(
4672 GeneralizedTime.tag_default +
4673 len_encode(len(junk)) +
4679 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4680 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4682 binary(min_size=1, max_size=1),
4684 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4685 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4688 def test_junk_dm(self, part0, part1, part2):
4689 junk = part0 + part1 + part2
4690 assume(not (set(junk) <= set(digits.encode("ascii"))))
4691 with self.assertRaises(DecodeError):
4692 GeneralizedTime().decode(
4693 GeneralizedTime.tag_default +
4694 len_encode(len(junk)) +
4698 def test_ns_fractions(self):
4699 GeneralizedTime(b"20010101000000.000001Z")
4700 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4701 GeneralizedTime(b"20010101000000.0000001Z")
4703 def test_non_pure_integers(self):
4705 # b"20000102030405Z,
4712 b"20000102030405.+6Z",
4713 b"20000102030405.-6Z",
4720 b"20000102030405._6Z",
4721 b"20000102030405.6_Z",
4728 b"20000102030405. 6Z",
4735 b"20000102030405.6 Z",
4737 with self.assertRaises(DecodeError):
4738 GeneralizedTime(data)
4740 def test_aware(self):
4741 with assertRaisesRegex(self, ValueError, "only naive"):
4742 GeneralizedTime(datetime(2000, 1, 1, 1, tzinfo=UTC))
4745 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4746 base_klass = UTCTime
4748 min_datetime = datetime(2000, 1, 1)
4749 max_datetime = datetime(2049, 12, 31)
4750 evgen_mode_skip_value = False
4752 def additional_symmetric_check(self, value, obj_encoded):
4755 def test_repr_not_ready(self):
4756 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4759 def test_x690_vector_valid(self):
4767 def test_x690_vector_invalid(self):
4772 with self.assertRaises(DecodeError) as err:
4776 def test_go_vectors_invalid(self):
4802 # These ones are INVALID in *DER*, but accepted
4803 # by Go's encoding/asn1
4804 b"910506164540-0700",
4805 b"910506164540+0730",
4809 with self.assertRaises(DecodeError) as err:
4813 def test_go_vectors_valid(self):
4815 UTCTime(b"910506234540Z").todatetime(),
4816 datetime(1991, 5, 6, 23, 45, 40, 0),
4819 def test_non_pure_integers(self):
4848 with self.assertRaises(DecodeError):
4851 def test_x680_vector_valid_ber(self):
4853 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4854 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4855 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4856 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4858 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4859 obj = UTCTime().decod(data_der, ctx={"bered": True})
4860 self.assertEqual(obj, dt)
4861 self.assertEqual(obj.todatetime(), dt)
4862 self.assertTrue(obj.ber_encoded)
4863 self.assertTrue(obj.bered)
4864 self.assertEqual(obj.ber_raw, data)
4865 self.assertNotEqual(obj.encode(), data_der)
4868 def test_go_vectors_valid_ber(self):
4870 b"910506164540-0700",
4871 b"910506164540+0730",
4875 data = UTCTime.tag_default + len_encode(len(data)) + data
4876 obj = UTCTime().decod(data, ctx={"bered": True})
4877 self.assertTrue(obj.ber_encoded)
4878 self.assertTrue(obj.bered)
4879 self.assertNotEqual(obj.encode(), data)
4882 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4883 @given(data_strategy())
4884 def test_valid_ber(self, d):
4885 year = d.draw(integers(min_value=0, max_value=99))
4886 month = d.draw(integers(min_value=1, max_value=12))
4887 day = d.draw(integers(min_value=1, max_value=28))
4888 hours = d.draw(integers(min_value=0, max_value=23))
4889 minute = d.draw(integers(min_value=0, max_value=59))
4890 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4892 year + (2000 if year < 50 else 1900),
4899 if d.draw(booleans()):
4901 seconds = d.draw(integers(min_value=0, max_value=59))
4902 data += "%02d" % seconds
4903 dt += timedelta(seconds=seconds)
4904 if d.draw(booleans()):
4908 offset_hour = d.draw(integers(min_value=0, max_value=13))
4909 offset_minute = d.draw(integers(min_value=0, max_value=59))
4910 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4911 if d.draw(booleans()):
4917 data += "%02d%02d" % (offset_hour, offset_minute)
4918 data = data.encode("ascii")
4919 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4920 obj = UTCTime().decod(data_der, ctx={"bered": True})
4921 self.assertEqual(obj, dt)
4922 self.assertEqual(obj.todatetime(), dt)
4923 self.assertEqual(obj.ber_encoded, not dered)
4924 self.assertEqual(obj.bered, not dered)
4925 self.assertEqual(obj.ber_raw, None if dered else data)
4926 self.assertEqual(obj.encode() == data_der, dered)
4931 def test_invalid_ber(self):
4972 b"0001020304+0000Z",
4981 with self.assertRaises(DecodeError):
4982 UTCTime(data, ctx={"bered": True})
4983 data = data[:8] + data[8+2:]
4984 with self.assertRaises(DecodeError):
4985 UTCTime(data, ctx={"bered": True})
5030 b"000102030405+000",
5031 b"000102030405+000Z",
5032 b"000102030405+0000Z",
5033 b"000102030405+-101",
5034 b"000102030405+01-1",
5035 b"000102030405+0060",
5036 b"000102030405+1401",
5037 b"500101000002+0003",
5039 with self.assertRaises(DecodeError):
5040 UTCTime(data, ctx={"bered": True})
5042 @given(integers(min_value=0, max_value=49))
5043 def test_pre50(self, year):
5045 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5049 @given(integers(min_value=50, max_value=99))
5050 def test_post50(self, year):
5052 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5058 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5059 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5061 binary(min_size=1, max_size=1),
5063 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5064 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5067 def test_junk(self, part0, part1, part2):
5068 junk = part0 + part1 + part2
5069 assume(not (set(junk) <= set(digits.encode("ascii"))))
5070 with self.assertRaises(DecodeError):
5072 UTCTime.tag_default +
5073 len_encode(len(junk)) +
5077 def test_aware(self):
5078 with assertRaisesRegex(self, ValueError, "only naive"):
5079 UTCTime(datetime(2000, 1, 1, 1, tzinfo=UTC))
5083 def tlv_value_strategy(draw):
5084 tag_num = draw(integers(min_value=1))
5085 data = draw(binary())
5086 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5090 def any_values_strategy(draw, do_expl=False):
5091 value = draw(one_of(none(), tlv_value_strategy()))
5094 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5095 optional = draw(one_of(none(), booleans()))
5097 draw(integers(min_value=0)),
5098 draw(integers(min_value=0)),
5099 draw(integers(min_value=0)),
5101 return (value, expl, optional, _decoded)
5104 class AnyInherited(Any):
5108 class TestAny(CommonMixin, TestCase):
5111 def test_invalid_value_type(self):
5112 with self.assertRaises(InvalidValueType) as err:
5117 def test_optional(self, optional):
5118 obj = Any(optional=optional)
5119 self.assertEqual(obj.optional, optional)
5121 @given(tlv_value_strategy())
5122 def test_ready(self, value):
5124 self.assertFalse(obj.ready)
5127 pprint(obj, big_blobs=True, with_decode_path=True)
5128 with self.assertRaises(ObjNotReady) as err:
5131 with self.assertRaises(ObjNotReady) as err:
5134 self.assertTrue(obj.ready)
5137 pprint(obj, big_blobs=True, with_decode_path=True)
5140 def test_basic(self, value):
5141 integer_encoded = Integer(value).encode()
5143 Any(integer_encoded),
5144 Any(Integer(value)),
5145 Any(Any(Integer(value))),
5147 self.assertSequenceEqual(bytes(obj), integer_encoded)
5149 obj.decode(obj.encode())[0].vlen,
5150 len(integer_encoded),
5154 pprint(obj, big_blobs=True, with_decode_path=True)
5155 self.assertSequenceEqual(obj.encode(), integer_encoded)
5157 @given(tlv_value_strategy(), tlv_value_strategy())
5158 def test_comparison(self, value1, value2):
5159 for klass in (Any, AnyInherited):
5160 obj1 = klass(value1)
5161 obj2 = klass(value2)
5162 self.assertEqual(obj1 == obj2, value1 == value2)
5163 self.assertEqual(obj1 != obj2, value1 != value2)
5164 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5166 @given(data_strategy())
5167 def test_call(self, d):
5168 for klass in (Any, AnyInherited):
5174 ) = d.draw(any_values_strategy())
5175 obj_initial = klass(
5178 optional_initial or False,
5186 ) = d.draw(any_values_strategy(do_expl=True))
5187 obj = obj_initial(value, expl, optional)
5189 value_expected = None if value is None else value
5190 self.assertEqual(obj, value_expected)
5191 self.assertEqual(obj.expl_tag, expl or expl_initial)
5192 if obj.default is None:
5193 optional = optional_initial if optional is None else optional
5194 optional = False if optional is None else optional
5195 self.assertEqual(obj.optional, optional)
5197 def test_simultaneous_impl_expl(self):
5198 # override it, as Any does not have implicit tag
5201 def test_decoded(self):
5202 # override it, as Any does not have implicit tag
5205 @given(any_values_strategy())
5206 def test_copy(self, values):
5207 for klass in (Any, AnyInherited):
5208 obj = klass(*values)
5209 for copy_func in copy_funcs:
5210 obj_copied = copy_func(obj)
5211 self.assert_copied_basic_fields(obj, obj_copied)
5212 self.assertEqual(obj._value, obj_copied._value)
5214 @given(binary().map(OctetString))
5215 def test_stripped(self, value):
5217 with self.assertRaises(NotEnoughData):
5218 obj.decode(obj.encode()[:-1])
5221 tlv_value_strategy(),
5222 integers(min_value=1).map(tag_ctxc),
5224 def test_stripped_expl(self, value, tag_expl):
5225 obj = Any(value, expl=tag_expl)
5226 with self.assertRaises(NotEnoughData):
5227 obj.decode(obj.encode()[:-1])
5230 integers(min_value=31),
5231 integers(min_value=0),
5234 def test_bad_tag(self, tag, offset, decode_path):
5235 with self.assertRaises(DecodeError) as err:
5237 tag_encode(tag)[:-1],
5239 decode_path=decode_path,
5242 self.assertEqual(err.exception.offset, offset)
5243 self.assertEqual(err.exception.decode_path, decode_path)
5246 integers(min_value=128),
5247 integers(min_value=0),
5250 def test_bad_len(self, l, offset, decode_path):
5251 with self.assertRaises(DecodeError) as err:
5253 Any.tag_default + len_encode(l)[:-1],
5255 decode_path=decode_path,
5258 self.assertEqual(err.exception.offset, offset)
5259 self.assertEqual(err.exception.decode_path, decode_path)
5261 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5263 any_values_strategy(),
5264 integers().map(lambda x: Integer(x).encode()),
5265 integers(min_value=1).map(tag_ctxc),
5266 integers(min_value=0),
5270 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5271 for klass in (Any, AnyInherited):
5272 _, _, optional, _decoded = values
5273 obj = klass(value=value, optional=optional, _decoded=_decoded)
5276 pprint(obj, big_blobs=True, with_decode_path=True)
5277 self.assertFalse(obj.expled)
5278 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5279 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5280 obj_encoded = obj.encode()
5281 self.assertEqual(encode2pass(obj), obj_encoded)
5282 obj_expled = obj(value, expl=tag_expl)
5283 self.assertTrue(obj_expled.expled)
5284 tag_class, _, tag_num = tag_decode(tag_expl)
5285 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5287 list(obj_expled.pps())
5288 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5289 obj_expled_encoded = obj_expled.encode()
5290 ctx_copied = deepcopy(ctx_dummy)
5291 obj_decoded, tail = obj_expled.decode(
5292 obj_expled_encoded + tail_junk,
5296 self.assertDictEqual(ctx_copied, ctx_dummy)
5298 list(obj_decoded.pps())
5299 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5300 self.assertEqual(tail, tail_junk)
5301 self.assertEqual(obj_decoded, obj_expled)
5302 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5303 self.assertEqual(bytes(obj_decoded), bytes(obj))
5304 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5305 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5306 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5308 obj_decoded.expl_llen,
5309 len(len_encode(len(obj_encoded))),
5311 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5312 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5315 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5317 self.assertEqual(obj_decoded.expl_offset, offset)
5318 self.assertEqual(obj_decoded.tlen, 0)
5319 self.assertEqual(obj_decoded.llen, 0)
5320 self.assertEqual(obj_decoded.vlen, len(value))
5321 assert_exceeding_data(
5323 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5327 evgens = list(obj_expled.decode_evgen(
5328 obj_expled_encoded + tail_junk,
5330 decode_path=decode_path,
5333 self.assertEqual(len(evgens), 1)
5334 _decode_path, obj, tail = evgens[0]
5335 self.assertSequenceEqual(tail, tail_junk)
5336 self.assertEqual(_decode_path, decode_path)
5337 self.assertEqual(obj.expl_offset, offset)
5342 integers(min_value=1).map(tag_ctxc),
5343 integers(min_value=0, max_value=3),
5344 integers(min_value=0),
5348 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5349 chunk = Boolean(False, expl=expl).encode()
5351 OctetString.tag_default +
5353 b"".join([chunk] * chunks) +
5356 with self.assertRaises(LenIndefForm):
5360 decode_path=decode_path,
5362 obj, tail = Any().decode(
5365 decode_path=decode_path,
5366 ctx={"bered": True},
5368 self.assertSequenceEqual(tail, junk)
5369 self.assertEqual(obj.offset, offset)
5370 self.assertEqual(obj.tlvlen, len(encoded))
5371 self.assertTrue(obj.lenindef)
5372 self.assertFalse(obj.ber_encoded)
5373 self.assertTrue(obj.bered)
5375 self.assertTrue(obj.lenindef)
5376 self.assertFalse(obj.ber_encoded)
5377 self.assertTrue(obj.bered)
5380 pprint(obj, big_blobs=True, with_decode_path=True)
5381 with self.assertRaises(NotEnoughData) as err:
5385 decode_path=decode_path,
5386 ctx={"bered": True},
5388 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5389 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5391 class SeqOf(SequenceOf):
5392 schema = Boolean(expl=expl)
5394 class Seq(Sequence):
5396 ("type", ObjectIdentifier(defines=((("value",), {
5397 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5402 ("type", ObjectIdentifier("1.2.3")),
5403 ("value", Any(encoded)),
5405 seq_encoded = seq.encode()
5406 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5407 self.assertIsNotNone(seq_decoded["value"].defined)
5409 list(seq_decoded.pps())
5410 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5411 self.assertTrue(seq_decoded.bered)
5412 self.assertFalse(seq_decoded["type"].bered)
5413 self.assertTrue(seq_decoded["value"].bered)
5415 chunk = chunk[:-1] + b"\x01"
5416 chunks = b"".join([chunk] * (chunks + 1))
5417 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5419 ("type", ObjectIdentifier("1.2.3")),
5420 ("value", Any(encoded)),
5422 seq_encoded = seq.encode()
5423 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5424 self.assertIsNotNone(seq_decoded["value"].defined)
5426 list(seq_decoded.pps())
5427 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5428 self.assertTrue(seq_decoded.bered)
5429 self.assertFalse(seq_decoded["type"].bered)
5430 self.assertTrue(seq_decoded["value"].bered)
5434 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5436 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5437 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5439 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5440 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5442 min_size=len(names),
5443 max_size=len(names),
5446 (name, Integer(**tag_kwargs))
5447 for name, tag_kwargs in zip(names, tags)
5450 if value_required or draw(booleans()):
5451 value = draw(tuples(
5452 sampled_from([name for name, _ in schema]),
5453 integers().map(Integer),
5457 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5458 default = draw(one_of(
5460 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5462 optional = draw(one_of(none(), booleans()))
5464 draw(integers(min_value=0)),
5465 draw(integers(min_value=0)),
5466 draw(integers(min_value=0)),
5468 return (schema, value, expl, default, optional, _decoded)
5471 class ChoiceInherited(Choice):
5475 class TestChoice(CommonMixin, TestCase):
5477 schema = (("whatever", Boolean()),)
5480 def test_schema_required(self):
5481 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5484 def test_impl_forbidden(self):
5485 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5486 Choice(impl=b"whatever")
5488 def test_invalid_value_type(self):
5489 with self.assertRaises(InvalidValueType) as err:
5490 self.base_klass(123)
5492 with self.assertRaises(ObjUnknown) as err:
5493 self.base_klass(("whenever", Boolean(False)))
5495 with self.assertRaises(InvalidValueType) as err:
5496 self.base_klass(("whatever", Integer(123)))
5500 def test_optional(self, optional):
5501 obj = self.base_klass(
5502 default=self.base_klass(("whatever", Boolean(False))),
5505 self.assertTrue(obj.optional)
5508 def test_ready(self, value):
5509 obj = self.base_klass()
5510 self.assertFalse(obj.ready)
5513 pprint(obj, big_blobs=True, with_decode_path=True)
5514 self.assertIsNone(obj["whatever"])
5515 with self.assertRaises(ObjNotReady) as err:
5518 with self.assertRaises(ObjNotReady) as err:
5520 obj["whatever"] = Boolean()
5521 self.assertFalse(obj.ready)
5524 pprint(obj, big_blobs=True, with_decode_path=True)
5525 obj["whatever"] = Boolean(value)
5526 self.assertTrue(obj.ready)
5529 pprint(obj, big_blobs=True, with_decode_path=True)
5531 @given(booleans(), booleans())
5532 def test_comparison(self, value1, value2):
5533 class WahlInherited(self.base_klass):
5535 for klass in (self.base_klass, WahlInherited):
5536 obj1 = klass(("whatever", Boolean(value1)))
5537 obj2 = klass(("whatever", Boolean(value2)))
5538 self.assertEqual(obj1 == obj2, value1 == value2)
5539 self.assertEqual(obj1 != obj2, value1 != value2)
5540 self.assertEqual(obj1 == obj2._value, value1 == value2)
5541 self.assertFalse(obj1 == obj2._value[1])
5543 @given(data_strategy())
5544 def test_call(self, d):
5545 for klass in (Choice, ChoiceInherited):
5553 ) = d.draw(choice_values_strategy())
5556 schema = schema_initial
5558 value=value_initial,
5560 default=default_initial,
5561 optional=optional_initial or False,
5562 _decoded=_decoded_initial,
5571 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5572 obj = obj_initial(value, expl, default, optional)
5574 value_expected = default if value is None else value
5576 default_initial if value_expected is None
5579 self.assertEqual(obj.choice, value_expected[0])
5580 self.assertEqual(obj.value, int(value_expected[1]))
5581 self.assertEqual(obj.expl_tag, expl or expl_initial)
5582 default_expect = default_initial if default is None else default
5583 if default_expect is not None:
5584 self.assertEqual(obj.default.choice, default_expect[0])
5585 self.assertEqual(obj.default.value, int(default_expect[1]))
5586 if obj.default is None:
5587 optional = optional_initial if optional is None else optional
5588 optional = False if optional is None else optional
5591 self.assertEqual(obj.optional, optional)
5592 self.assertEqual(obj.specs, obj_initial.specs)
5594 def test_simultaneous_impl_expl(self):
5595 # override it, as Any does not have implicit tag
5598 def test_decoded(self):
5599 # override it, as Any does not have implicit tag
5602 @given(choice_values_strategy())
5603 def test_copy(self, values):
5604 _schema, value, expl, default, optional, _decoded = values
5606 class Wahl(self.base_klass):
5608 register_class(Wahl)
5613 optional=optional or False,
5616 for copy_func in copy_funcs:
5617 obj_copied = copy_func(obj)
5618 self.assertIsNone(obj.tag)
5619 self.assertIsNone(obj_copied.tag)
5620 # hack for assert_copied_basic_fields
5621 obj.tag = "whatever"
5622 obj_copied.tag = "whatever"
5623 self.assert_copied_basic_fields(obj, obj_copied)
5625 self.assertEqual(obj._value, obj_copied._value)
5626 self.assertEqual(obj.specs, obj_copied.specs)
5629 def test_stripped(self, value):
5630 obj = self.base_klass(("whatever", Boolean(value)))
5631 with self.assertRaises(NotEnoughData):
5632 obj.decode(obj.encode()[:-1])
5636 integers(min_value=1).map(tag_ctxc),
5638 def test_stripped_expl(self, value, tag_expl):
5639 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5640 with self.assertRaises(NotEnoughData):
5641 obj.decode(obj.encode()[:-1])
5643 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5644 @given(data_strategy())
5645 def test_symmetric(self, d):
5646 _schema, value, _, default, optional, _decoded = d.draw(
5647 choice_values_strategy(value_required=True)
5649 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5650 offset = d.draw(integers(min_value=0))
5651 tail_junk = d.draw(binary(max_size=5))
5652 decode_path = d.draw(decode_path_strat)
5654 class Wahl(self.base_klass):
5664 pprint(obj, big_blobs=True, with_decode_path=True)
5665 self.assertFalse(obj.expled)
5666 self.assertEqual(obj.tag_order, obj.value.tag_order)
5667 obj_encoded = obj.encode()
5668 self.assertEqual(encode2pass(obj), obj_encoded)
5669 obj_expled = obj(value, expl=tag_expl)
5670 self.assertTrue(obj_expled.expled)
5671 tag_class, _, tag_num = tag_decode(tag_expl)
5672 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5674 list(obj_expled.pps())
5675 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5676 obj_expled_encoded = obj_expled.encode()
5677 ctx_copied = deepcopy(ctx_dummy)
5678 obj_decoded, tail = obj_expled.decode(
5679 obj_expled_encoded + tail_junk,
5683 self.assertDictEqual(ctx_copied, ctx_dummy)
5685 list(obj_decoded.pps())
5686 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5687 self.assertEqual(tail, tail_junk)
5688 self.assertEqual(obj_decoded, obj_expled)
5689 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5690 self.assertEqual(obj_decoded.value, obj_expled.value)
5691 self.assertEqual(obj_decoded.choice, obj.choice)
5692 self.assertEqual(obj_decoded.value, obj.value)
5693 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5694 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5695 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5697 obj_decoded.expl_llen,
5698 len(len_encode(len(obj_encoded))),
5700 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5701 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5704 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5706 self.assertEqual(obj_decoded.expl_offset, offset)
5707 self.assertSequenceEqual(
5709 obj_decoded.value.fulloffset - offset:
5710 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5714 assert_exceeding_data(
5716 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5720 evgens = list(obj_expled.decode_evgen(
5721 obj_expled_encoded + tail_junk,
5723 decode_path=decode_path,
5726 self.assertEqual(len(evgens), 2)
5727 _decode_path, obj, tail = evgens[0]
5728 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5729 _decode_path, obj, tail = evgens[1]
5730 self.assertSequenceEqual(tail, tail_junk)
5731 self.assertEqual(_decode_path, decode_path)
5732 self.assertEqual(obj.expl_offset, offset)
5737 def test_set_get(self, value):
5740 ("erste", Boolean()),
5741 ("zweite", Integer()),
5744 with self.assertRaises(ObjUnknown) as err:
5745 obj["whatever"] = "whenever"
5746 with self.assertRaises(InvalidValueType) as err:
5747 obj["zweite"] = Boolean(False)
5748 obj["zweite"] = Integer(value)
5750 with self.assertRaises(ObjUnknown) as err:
5753 self.assertIsNone(obj["erste"])
5754 self.assertEqual(obj["zweite"], Integer(value))
5756 def test_tag_mismatch(self):
5759 ("erste", Boolean()),
5761 int_encoded = Integer(123).encode()
5762 bool_encoded = Boolean(False).encode()
5764 obj.decode(bool_encoded)
5765 with self.assertRaises(TagMismatch):
5766 obj.decode(int_encoded)
5768 def test_tag_mismatch_underlying(self):
5769 class SeqOfBoolean(SequenceOf):
5772 class SeqOfInteger(SequenceOf):
5777 ("erste", SeqOfBoolean()),
5780 int_encoded = SeqOfInteger((Integer(123),)).encode()
5781 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5783 obj.decode(bool_encoded)
5784 with self.assertRaises(TagMismatch) as err:
5785 obj.decode(int_encoded)
5786 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5790 def seq_values_strategy(draw, seq_klass, do_expl=False):
5792 if draw(booleans()):
5794 value._value = draw(dictionaries(
5797 booleans().map(Boolean),
5798 integers().map(Integer),
5802 if draw(booleans()):
5803 schema = list(draw(dictionaries(
5806 booleans().map(Boolean),
5807 integers().map(Integer),
5813 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5815 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5817 if draw(booleans()):
5818 default = seq_klass()
5819 default._value = draw(dictionaries(
5822 booleans().map(Boolean),
5823 integers().map(Integer),
5826 optional = draw(one_of(none(), booleans()))
5828 draw(integers(min_value=0)),
5829 draw(integers(min_value=0)),
5830 draw(integers(min_value=0)),
5832 return (value, schema, impl, expl, default, optional, _decoded)
5836 def sequence_strategy(draw, seq_klass):
5837 inputs = draw(lists(
5839 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5840 tuples(just(Integer), integers(), one_of(none(), integers())),
5845 integers(min_value=1),
5846 min_size=len(inputs),
5847 max_size=len(inputs),
5850 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5851 for tag, expled in zip(tags, draw(lists(
5853 min_size=len(inputs),
5854 max_size=len(inputs),
5858 for i, optional in enumerate(draw(lists(
5859 sampled_from(("required", "optional", "empty")),
5860 min_size=len(inputs),
5861 max_size=len(inputs),
5863 if optional in ("optional", "empty"):
5864 inits[i]["optional"] = True
5865 if optional == "empty":
5867 empties = set(empties)
5868 names = list(draw(sets(
5870 min_size=len(inputs),
5871 max_size=len(inputs),
5874 for i, (klass, value, default) in enumerate(inputs):
5875 schema.append((names[i], klass(default=default, **inits[i])))
5876 seq_name = draw(text_letters())
5877 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5880 for i, (klass, value, default) in enumerate(inputs):
5887 "default_value": None if spec.default is None else default,
5891 expect["optional"] = True
5893 expect["presented"] = True
5894 expect["value"] = value
5896 expect["optional"] = True
5897 if default is not None and default == value:
5898 expect["presented"] = False
5899 seq[name] = klass(value)
5900 expects.append(expect)
5905 def sequences_strategy(draw, seq_klass):
5906 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5908 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5909 for tag, expled in zip(tags, draw(lists(
5916 i for i, is_default in enumerate(draw(lists(
5922 names = list(draw(sets(
5927 seq_expectses = draw(lists(
5928 sequence_strategy(seq_klass=seq_klass),
5932 seqs = [seq for seq, _ in seq_expectses]
5934 for i, (name, seq) in enumerate(zip(names, seqs)):
5937 seq(default=(seq if i in defaulted else None), **inits[i]),
5939 seq_name = draw(text_letters())
5940 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5943 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5946 "expects": expects_inner,
5949 seq_outer[name] = seq_inner
5950 if seq_outer.specs[name].default is None:
5951 expect["presented"] = True
5952 expect_outers.append(expect)
5953 return seq_outer, expect_outers
5956 class SeqMixing(object):
5957 def test_invalid_value_type(self):
5958 with self.assertRaises(InvalidValueType) as err:
5959 self.base_klass(123)
5962 def test_invalid_value_type_set(self):
5963 class Seq(self.base_klass):
5964 schema = (("whatever", Boolean()),)
5966 with self.assertRaises(InvalidValueType) as err:
5967 seq["whatever"] = Integer(123)
5971 def test_optional(self, optional):
5972 obj = self.base_klass(default=self.base_klass(), optional=optional)
5973 self.assertTrue(obj.optional)
5975 @given(data_strategy())
5976 def test_ready(self, d):
5978 str(i): v for i, v in enumerate(d.draw(lists(
5985 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5992 for name in d.draw(permutations(
5993 list(ready.keys()) + list(non_ready.keys()),
5995 schema_input.append((name, Boolean()))
5997 class Seq(self.base_klass):
5998 schema = tuple(schema_input)
6000 for name in ready.keys():
6002 seq[name] = Boolean()
6003 self.assertFalse(seq.ready)
6006 pprint(seq, big_blobs=True, with_decode_path=True)
6007 for name, value in ready.items():
6008 seq[name] = Boolean(value)
6009 self.assertFalse(seq.ready)
6012 pprint(seq, big_blobs=True, with_decode_path=True)
6013 with self.assertRaises(ObjNotReady) as err:
6016 with self.assertRaises(ObjNotReady) as err:
6018 for name, value in non_ready.items():
6019 seq[name] = Boolean(value)
6020 self.assertTrue(seq.ready)
6023 pprint(seq, big_blobs=True, with_decode_path=True)
6025 @given(data_strategy())
6026 def test_call(self, d):
6027 class SeqInherited(self.base_klass):
6029 for klass in (self.base_klass, SeqInherited):
6038 ) = d.draw(seq_values_strategy(seq_klass=klass))
6039 obj_initial = klass(
6045 optional_initial or False,
6056 ) = d.draw(seq_values_strategy(
6058 do_expl=impl_initial is None,
6060 obj = obj_initial(value, impl, expl, default, optional)
6061 value_expected = default if value is None else value
6063 default_initial if value_expected is None
6066 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
6067 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6068 self.assertEqual(obj.expl_tag, expl or expl_initial)
6070 {} if obj.default is None else obj.default._value,
6071 getattr(default_initial if default is None else default, "_value", {}),
6073 if obj.default is None:
6074 optional = optional_initial if optional is None else optional
6075 optional = False if optional is None else optional
6078 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6079 self.assertEqual(obj.optional, optional)
6081 @given(data_strategy())
6082 def test_copy(self, d):
6083 class SeqInherited(self.base_klass):
6085 register_class(SeqInherited)
6086 for klass in (self.base_klass, SeqInherited):
6087 values = d.draw(seq_values_strategy(seq_klass=klass))
6088 obj = klass(*values)
6089 for copy_func in copy_funcs:
6090 obj_copied = copy_func(obj)
6091 self.assert_copied_basic_fields(obj, obj_copied)
6092 self.assertEqual(obj.specs, obj_copied.specs)
6093 self.assertEqual(obj._value, obj_copied._value)
6095 @given(data_strategy())
6096 def test_stripped(self, d):
6097 value = d.draw(integers())
6098 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6100 class Seq(self.base_klass):
6102 schema = (("whatever", Integer()),)
6104 seq["whatever"] = Integer(value)
6105 with self.assertRaises(NotEnoughData):
6106 seq.decode(seq.encode()[:-1])
6108 @given(data_strategy())
6109 def test_stripped_expl(self, d):
6110 value = d.draw(integers())
6111 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6113 class Seq(self.base_klass):
6115 schema = (("whatever", Integer()),)
6117 seq["whatever"] = Integer(value)
6118 with self.assertRaises(NotEnoughData):
6119 seq.decode(seq.encode()[:-1])
6121 @given(integers(min_value=3), binary(min_size=2))
6122 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6123 junk = tag_encode(junk_tag_num) + junk
6125 _, _, len_encoded = tag_strip(memoryview(junk))
6126 len_decode(len_encoded)
6132 class Seq(self.base_klass):
6134 ("whatever", Integer()),
6136 ("whenever", Integer()),
6139 seq["whatever"] = Integer(123)
6140 seq["junk"] = Any(junk)
6141 seq["whenever"] = Integer(123)
6142 with self.assertRaises(DecodeError):
6143 seq.decode(seq.encode())
6146 integers(min_value=31),
6147 integers(min_value=0),
6150 def test_bad_tag(self, tag, offset, decode_path):
6151 with self.assertRaises(DecodeError) as err:
6152 self.base_klass().decode(
6153 tag_encode(tag)[:-1],
6155 decode_path=decode_path,
6158 self.assertEqual(err.exception.offset, offset)
6159 self.assertEqual(err.exception.decode_path, decode_path)
6162 integers(min_value=128),
6163 integers(min_value=0),
6166 def test_bad_len(self, l, offset, decode_path):
6167 with self.assertRaises(DecodeError) as err:
6168 self.base_klass().decode(
6169 self.base_klass.tag_default + len_encode(l)[:-1],
6171 decode_path=decode_path,
6174 self.assertEqual(err.exception.offset, offset)
6175 self.assertEqual(err.exception.decode_path, decode_path)
6177 def _assert_expects(self, seq, expects):
6178 for expect in expects:
6180 seq.specs[expect["name"]].optional,
6183 if expect["default_value"] is not None:
6185 seq.specs[expect["name"]].default,
6186 expect["default_value"],
6188 if expect["presented"]:
6189 self.assertIn(expect["name"], seq)
6190 self.assertEqual(seq[expect["name"]], expect["value"])
6192 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6193 @given(data_strategy())
6194 def test_symmetric(self, d):
6195 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6196 tail_junk = d.draw(binary(max_size=5))
6197 decode_path = d.draw(decode_path_strat)
6198 self.assertTrue(seq.ready)
6199 self.assertFalse(seq.decoded)
6200 self._assert_expects(seq, expects)
6203 pprint(seq, big_blobs=True, with_decode_path=True)
6204 self.assertTrue(seq.ready)
6205 seq_encoded = seq.encode()
6206 self.assertEqual(encode2pass(seq), seq_encoded)
6207 seq_encoded_cer = encode_cer(seq)
6208 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6209 self.assertSequenceEqual(
6210 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6213 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6214 self.assertFalse(seq_decoded.lenindef)
6215 self.assertFalse(seq_decoded.ber_encoded)
6216 self.assertFalse(seq_decoded.bered)
6218 t, _, lv = tag_strip(seq_encoded)
6219 _, _, v = len_decode(lv)
6220 seq_encoded_lenindef = t + LENINDEF + v + EOC
6221 with self.assertRaises(DecodeError):
6222 seq.decode(seq_encoded_lenindef)
6223 ctx_copied = deepcopy(ctx_dummy)
6224 ctx_copied["bered"] = True
6225 seq_decoded_lenindef, tail_lenindef = seq.decode(
6226 seq_encoded_lenindef + tail_junk,
6229 del ctx_copied["bered"]
6230 self.assertDictEqual(ctx_copied, ctx_dummy)
6231 self.assertTrue(seq_decoded_lenindef.lenindef)
6232 self.assertTrue(seq_decoded_lenindef.bered)
6233 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6234 self.assertTrue(seq_decoded_lenindef.lenindef)
6235 self.assertTrue(seq_decoded_lenindef.bered)
6236 with self.assertRaises(DecodeError):
6237 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6238 with self.assertRaises(DecodeError):
6239 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6240 repr(seq_decoded_lenindef)
6241 list(seq_decoded_lenindef.pps())
6242 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6243 self.assertTrue(seq_decoded_lenindef.ready)
6245 for decoded, decoded_tail, encoded in (
6246 (seq_decoded, tail, seq_encoded),
6247 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6249 self.assertEqual(decoded_tail, tail_junk)
6250 self._assert_expects(decoded, expects)
6251 self.assertEqual(seq, decoded)
6252 self.assertEqual(decoded.encode(), seq_encoded)
6253 self.assertEqual(decoded.tlvlen, len(encoded))
6254 for expect in expects:
6255 if not expect["presented"]:
6256 self.assertNotIn(expect["name"], decoded)
6258 self.assertIn(expect["name"], decoded)
6259 obj = decoded[expect["name"]]
6260 self.assertTrue(obj.decoded)
6261 offset = obj.expl_offset if obj.expled else obj.offset
6262 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6263 self.assertSequenceEqual(
6264 seq_encoded[offset:offset + tlvlen],
6268 evgens = list(seq.decode_evgen(
6269 encoded + decoded_tail,
6270 decode_path=decode_path,
6271 ctx={"bered": True},
6273 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6274 for _decode_path, obj, _ in evgens[:-1]:
6275 self.assertEqual(_decode_path[:-1], decode_path)
6278 _decode_path, obj, tail = evgens[-1]
6279 self.assertEqual(_decode_path, decode_path)
6283 assert_exceeding_data(
6285 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6289 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6290 @given(data_strategy())
6291 def test_symmetric_with_seq(self, d):
6292 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6293 self.assertTrue(seq.ready)
6294 seq_encoded = seq.encode()
6295 self.assertEqual(encode2pass(seq), seq_encoded)
6296 seq_decoded, tail = seq.decode(seq_encoded)
6297 self.assertEqual(tail, b"")
6298 self.assertTrue(seq.ready)
6299 self.assertEqual(seq, seq_decoded)
6300 self.assertEqual(seq_decoded.encode(), seq_encoded)
6301 for expect_outer in expect_outers:
6302 if not expect_outer["presented"]:
6303 self.assertNotIn(expect_outer["name"], seq_decoded)
6305 self.assertIn(expect_outer["name"], seq_decoded)
6306 obj = seq_decoded[expect_outer["name"]]
6307 self.assertTrue(obj.decoded)
6308 offset = obj.expl_offset if obj.expled else obj.offset
6309 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6310 self.assertSequenceEqual(
6311 seq_encoded[offset:offset + tlvlen],
6314 self._assert_expects(obj, expect_outer["expects"])
6316 @given(data_strategy())
6317 def test_default_disappears(self, d):
6318 _schema = list(d.draw(dictionaries(
6320 sets(integers(), min_size=2, max_size=2),
6324 class Seq(self.base_klass):
6326 (n, Integer(default=d))
6327 for n, (_, d) in _schema
6330 for name, (value, _) in _schema:
6331 seq[name] = Integer(value)
6332 self.assertEqual(len(seq._value), len(_schema))
6333 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6334 self.assertGreater(len(seq.encode()), len(empty_seq))
6335 for name, (_, default) in _schema:
6336 seq[name] = Integer(default)
6337 self.assertEqual(len(seq._value), 0)
6338 self.assertSequenceEqual(seq.encode(), empty_seq)
6340 @given(data_strategy())
6341 def test_encoded_default_not_accepted(self, d):
6342 _schema = list(d.draw(dictionaries(
6347 tags = [tag_encode(tag) for tag in d.draw(sets(
6348 integers(min_value=1),
6349 min_size=len(_schema),
6350 max_size=len(_schema),
6354 schema = (("int", Integer()),)
6356 class SeqWithoutDefault(self.base_klass):
6359 for (n, _), t in zip(_schema, tags)
6361 seq_without_default = SeqWithoutDefault()
6362 for name, value in _schema:
6363 seq_without_default[name] = Wahl(("int", Integer(value)))
6364 seq_encoded = seq_without_default.encode()
6365 seq_without_default.decode(seq_encoded)
6367 len(list(seq_without_default.decode_evgen(seq_encoded))),
6368 len(_schema) * 2 + 1,
6371 class SeqWithDefault(self.base_klass):
6373 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6374 for (n, v), t in zip(_schema, tags)
6376 seq_with_default = SeqWithDefault()
6377 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6378 seq_with_default.decode(seq_encoded)
6379 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6380 list(seq_with_default.decode_evgen(seq_encoded))
6381 for ctx in ({"bered": True}, {"allow_default_values": True}):
6382 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6383 self.assertTrue(seq_decoded.ber_encoded)
6384 self.assertTrue(seq_decoded.bered)
6385 seq_decoded = copy(seq_decoded)
6386 self.assertTrue(seq_decoded.ber_encoded)
6387 self.assertTrue(seq_decoded.bered)
6388 for name, value in _schema:
6389 self.assertEqual(seq_decoded[name], seq_with_default[name])
6390 self.assertEqual(seq_decoded[name].value, value)
6392 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6396 seq_without_default = SeqWithoutDefault()
6397 for name, value in _schema:
6398 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6399 seq_encoded = seq_without_default.encode()
6400 seq_with_default.decode(seq_encoded)
6402 len(list(seq_with_default.decode_evgen(seq_encoded))),
6406 @given(data_strategy())
6407 def test_missing_from_spec(self, d):
6408 names = list(d.draw(sets(text_letters(), min_size=2)))
6409 tags = [tag_encode(tag) for tag in d.draw(sets(
6410 integers(min_value=1),
6411 min_size=len(names),
6412 max_size=len(names),
6414 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6416 class SeqFull(self.base_klass):
6417 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6418 seq_full = SeqFull()
6419 for i, name in enumerate(names):
6420 seq_full[name] = Integer(i)
6421 seq_encoded = seq_full.encode()
6422 altered = names_tags[:-2] + names_tags[-1:]
6424 class SeqMissing(self.base_klass):
6425 schema = [(n, Integer(impl=t)) for n, t in altered]
6426 seq_missing = SeqMissing()
6427 with self.assertRaises(TagMismatch):
6428 seq_missing.decode(seq_encoded)
6429 with self.assertRaises(TagMismatch):
6430 list(seq_missing.decode_evgen(seq_encoded))
6432 def test_bered(self):
6433 class Seq(self.base_klass):
6434 schema = (("underlying", Boolean()),)
6435 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6436 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6437 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6438 self.assertFalse(decoded.ber_encoded)
6439 self.assertFalse(decoded.lenindef)
6440 self.assertTrue(decoded.bered)
6441 decoded = copy(decoded)
6442 self.assertFalse(decoded.ber_encoded)
6443 self.assertFalse(decoded.lenindef)
6444 self.assertTrue(decoded.bered)
6446 class Seq(self.base_klass):
6447 schema = (("underlying", OctetString()),)
6449 tag_encode(form=TagFormConstructed, num=4) +
6451 OctetString(b"whatever").encode() +
6454 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6455 with self.assertRaises(DecodeError):
6456 Seq().decode(encoded)
6457 with self.assertRaises(DecodeError):
6458 list(Seq().decode_evgen(encoded))
6459 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6460 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6461 self.assertFalse(decoded.ber_encoded)
6462 self.assertFalse(decoded.lenindef)
6463 self.assertTrue(decoded.bered)
6464 decoded = copy(decoded)
6465 self.assertFalse(decoded.ber_encoded)
6466 self.assertFalse(decoded.lenindef)
6467 self.assertTrue(decoded.bered)
6470 class TestSequence(SeqMixing, CommonMixin, TestCase):
6471 base_klass = Sequence
6477 def test_remaining(self, value, junk):
6478 class Seq(Sequence):
6480 ("whatever", Integer()),
6482 int_encoded = Integer(value).encode()
6484 Sequence.tag_default,
6485 len_encode(len(int_encoded + junk)),
6488 with assertRaisesRegex(self, DecodeError, "remaining"):
6489 Seq().decode(junked)
6491 @given(sets(text_letters(), min_size=2))
6492 def test_obj_unknown(self, names):
6493 missing = names.pop()
6495 class Seq(Sequence):
6496 schema = [(n, Boolean()) for n in names]
6498 with self.assertRaises(ObjUnknown) as err:
6501 with self.assertRaises(ObjUnknown) as err:
6502 seq[missing] = Boolean()
6505 def test_x690_vector(self):
6506 class Seq(Sequence):
6508 ("name", IA5String()),
6511 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6512 self.assertEqual(seq["name"], "Smith")
6513 self.assertEqual(seq["ok"], True)
6516 class TestSet(SeqMixing, CommonMixin, TestCase):
6519 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6520 @given(data_strategy())
6521 def test_sorted(self, d):
6522 class DummySeq(Sequence):
6523 schema = (("null", Null()),)
6525 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6526 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6527 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6528 tag_nums -= set([dummy_seq_tag_num])
6529 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6530 _schema.append(("seq", DummySeq()))
6533 schema = d.draw(permutations(_schema))
6535 for name, _ in _schema:
6537 seq[name] = OctetString(name.encode("ascii"))
6538 seq["seq"] = DummySeq((("null", Null()),))
6540 seq_encoded = seq.encode()
6541 seq_decoded, _ = seq.decode(seq_encoded)
6542 seq_encoded_expected = []
6543 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6544 if tag_num == dummy_seq_tag_num:
6545 seq_encoded_expected.append(seq["seq"].encode())
6547 seq_encoded_expected.append(seq[str(tag_num)].encode())
6548 self.assertSequenceEqual(
6549 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6550 b"".join(seq_encoded_expected),
6553 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6554 encoded += seq["seq"].encode()
6555 seq_encoded = b"".join((
6557 len_encode(len(encoded)),
6560 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6561 seq.decode(seq_encoded)
6562 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6563 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6564 self.assertTrue(seq_decoded.ber_encoded)
6565 self.assertTrue(seq_decoded.bered)
6566 seq_decoded = copy(seq_decoded)
6567 self.assertTrue(seq_decoded.ber_encoded)
6568 self.assertTrue(seq_decoded.bered)
6570 def test_same_value_twice(self):
6573 ("bool", Boolean()),
6577 encoded = b"".join((
6578 Integer(123).encode(),
6579 Integer(234).encode(),
6580 Boolean(True).encode(),
6582 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6583 with self.assertRaises(TagMismatch):
6584 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6588 def seqof_values_strategy(draw, schema=None, do_expl=False):
6590 schema = draw(sampled_from((Boolean(), Integer())))
6591 bound_min, bound_max = sorted(draw(sets(
6592 integers(min_value=0, max_value=10),
6596 if isinstance(schema, Boolean):
6597 values_generator = booleans().map(Boolean)
6598 elif isinstance(schema, Integer):
6599 values_generator = integers().map(Integer)
6600 values_generator = lists(
6605 values = draw(one_of(none(), values_generator))
6609 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6611 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6612 default = draw(one_of(none(), values_generator))
6613 optional = draw(one_of(none(), booleans()))
6615 draw(integers(min_value=0)),
6616 draw(integers(min_value=0)),
6617 draw(integers(min_value=0)),
6622 (bound_min, bound_max),
6631 class SeqOfMixing(object):
6632 def test_invalid_value_type(self):
6633 with self.assertRaises(InvalidValueType) as err:
6634 self.base_klass(123)
6637 def test_invalid_values_type(self):
6638 class SeqOf(self.base_klass):
6640 with self.assertRaises(InvalidValueType) as err:
6641 SeqOf([Integer(123), Boolean(False), Integer(234)])
6644 def test_schema_required(self):
6645 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6646 self.base_klass.__mro__[1]()
6648 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6649 def test_comparison(self, value1, value2, tag1, tag2):
6650 class SeqOf(self.base_klass):
6652 obj1 = SeqOf([Boolean(value1)])
6653 obj2 = SeqOf([Boolean(value2)])
6654 self.assertEqual(obj1 == obj2, value1 == value2)
6655 self.assertEqual(obj1 != obj2, value1 != value2)
6656 self.assertEqual(obj1 == list(obj2), value1 == value2)
6657 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6658 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6659 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6660 self.assertEqual(obj1 == obj2, tag1 == tag2)
6661 self.assertEqual(obj1 != obj2, tag1 != tag2)
6663 @given(lists(booleans()))
6664 def test_iter(self, values):
6665 class SeqOf(self.base_klass):
6667 obj = SeqOf([Boolean(value) for value in values])
6668 self.assertEqual(len(obj), len(values))
6669 for i, value in enumerate(obj):
6670 self.assertEqual(value, values[i])
6672 @given(data_strategy())
6673 def test_ready(self, d):
6674 ready = [Integer(v) for v in d.draw(lists(
6681 range(d.draw(integers(min_value=1, max_value=5)))
6684 class SeqOf(self.base_klass):
6686 values = d.draw(permutations(ready + non_ready))
6688 for value in values:
6690 self.assertFalse(seqof.ready)
6693 pprint(seqof, big_blobs=True, with_decode_path=True)
6694 with self.assertRaises(ObjNotReady) as err:
6697 with self.assertRaises(ObjNotReady) as err:
6699 for i, value in enumerate(values):
6700 self.assertEqual(seqof[i], value)
6701 if not seqof[i].ready:
6702 seqof[i] = Integer(i)
6703 self.assertTrue(seqof.ready)
6706 pprint(seqof, big_blobs=True, with_decode_path=True)
6708 def test_spec_mismatch(self):
6709 class SeqOf(self.base_klass):
6712 seqof.append(Integer(123))
6713 with self.assertRaises(ValueError):
6714 seqof.append(Boolean(False))
6715 with self.assertRaises(ValueError):
6716 seqof[0] = Boolean(False)
6718 @given(data_strategy())
6719 def test_bounds_satisfied(self, d):
6720 class SeqOf(self.base_klass):
6722 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6723 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6724 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6725 SeqOf(value=value, bounds=(bound_min, bound_max))
6727 @given(data_strategy())
6728 def test_bounds_unsatisfied(self, d):
6729 class SeqOf(self.base_klass):
6731 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6732 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6733 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6734 with self.assertRaises(BoundsError) as err:
6735 SeqOf(value=value, bounds=(bound_min, bound_max))
6737 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6738 SeqOf(bounds=(bound_min, bound_max)).decode(
6739 SeqOf(value).encode()
6742 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6743 SeqOf(bounds=(bound_min, bound_max)).decode(
6744 encode2pass(SeqOf(value))
6746 value = [Boolean(True)] * d.draw(integers(
6747 min_value=bound_max + 1,
6748 max_value=bound_max + 10,
6750 with self.assertRaises(BoundsError) as err:
6751 SeqOf(value=value, bounds=(bound_min, bound_max))
6753 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6754 SeqOf(bounds=(bound_min, bound_max)).decode(
6755 SeqOf(value).encode()
6758 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6759 SeqOf(bounds=(bound_min, bound_max)).decode(
6760 encode2pass(SeqOf(value))
6763 @given(integers(min_value=1, max_value=10))
6764 def test_out_of_bounds(self, bound_max):
6765 class SeqOf(self.base_klass):
6767 bounds = (0, bound_max)
6769 for _ in range(bound_max):
6770 seqof.append(Integer(123))
6771 with self.assertRaises(BoundsError):
6772 seqof.append(Integer(123))
6774 @given(data_strategy())
6775 def test_call(self, d):
6785 ) = d.draw(seqof_values_strategy())
6787 class SeqOf(self.base_klass):
6788 schema = schema_initial
6789 obj_initial = SeqOf(
6790 value=value_initial,
6791 bounds=bounds_initial,
6794 default=default_initial,
6795 optional=optional_initial or False,
6796 _decoded=_decoded_initial,
6807 ) = d.draw(seqof_values_strategy(
6808 schema=schema_initial,
6809 do_expl=impl_initial is None,
6811 if (default is None) and (obj_initial.default is not None):
6814 (bounds is None) and
6815 (value is not None) and
6816 (bounds_initial is not None) and
6817 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6821 (bounds is None) and
6822 (default is not None) and
6823 (bounds_initial is not None) and
6824 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6836 value_expected = default if value is None else value
6838 default_initial if value_expected is None
6841 value_expected = () if value_expected is None else value_expected
6842 self.assertEqual(obj, value_expected)
6843 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6844 self.assertEqual(obj.expl_tag, expl or expl_initial)
6847 default_initial if default is None else default,
6849 if obj.default is None:
6850 optional = optional_initial if optional is None else optional
6851 optional = False if optional is None else optional
6854 self.assertEqual(obj.optional, optional)
6856 (obj._bound_min, obj._bound_max),
6857 bounds or bounds_initial or (0, float("+inf")),
6860 @given(seqof_values_strategy())
6861 def test_copy(self, values):
6862 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6864 class SeqOf(self.base_klass):
6866 register_class(SeqOf)
6873 optional=optional or False,
6876 for copy_func in copy_funcs:
6877 obj_copied = copy_func(obj)
6878 self.assert_copied_basic_fields(obj, obj_copied)
6879 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6880 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6881 self.assertEqual(obj._value, obj_copied._value)
6885 integers(min_value=1).map(tag_encode),
6887 def test_stripped(self, values, tag_impl):
6888 class SeqOf(self.base_klass):
6889 schema = OctetString()
6890 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6891 with self.assertRaises(NotEnoughData):
6892 obj.decode(obj.encode()[:-1])
6896 integers(min_value=1).map(tag_ctxc),
6898 def test_stripped_expl(self, values, tag_expl):
6899 class SeqOf(self.base_klass):
6900 schema = OctetString()
6901 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6902 with self.assertRaises(NotEnoughData):
6903 obj.decode(obj.encode()[:-1])
6906 integers(min_value=31),
6907 integers(min_value=0),
6910 def test_bad_tag(self, tag, offset, decode_path):
6911 with self.assertRaises(DecodeError) as err:
6912 self.base_klass().decode(
6913 tag_encode(tag)[:-1],
6915 decode_path=decode_path,
6918 self.assertEqual(err.exception.offset, offset)
6919 self.assertEqual(err.exception.decode_path, decode_path)
6922 integers(min_value=128),
6923 integers(min_value=0),
6926 def test_bad_len(self, l, offset, decode_path):
6927 with self.assertRaises(DecodeError) as err:
6928 self.base_klass().decode(
6929 self.base_klass.tag_default + len_encode(l)[:-1],
6931 decode_path=decode_path,
6934 self.assertEqual(err.exception.offset, offset)
6935 self.assertEqual(err.exception.decode_path, decode_path)
6937 @given(binary(min_size=1))
6938 def test_tag_mismatch(self, impl):
6939 assume(impl != self.base_klass.tag_default)
6940 with self.assertRaises(TagMismatch):
6941 self.base_klass(impl=impl).decode(self.base_klass().encode())
6943 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6945 seqof_values_strategy(schema=Integer()),
6946 lists(integers().map(Integer)),
6947 integers(min_value=1).map(tag_ctxc),
6948 integers(min_value=0),
6952 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6953 _, _, _, _, _, default, optional, _decoded = values
6955 class SeqOf(self.base_klass):
6965 pprint(obj, big_blobs=True, with_decode_path=True)
6966 self.assertFalse(obj.expled)
6967 obj_encoded = obj.encode()
6968 self.assertEqual(encode2pass(obj), obj_encoded)
6969 obj_encoded_cer = encode_cer(obj)
6970 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6971 self.assertSequenceEqual(
6972 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6975 obj_expled = obj(value, expl=tag_expl)
6976 self.assertTrue(obj_expled.expled)
6978 list(obj_expled.pps())
6979 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6980 obj_expled_encoded = obj_expled.encode()
6981 ctx_copied = deepcopy(ctx_dummy)
6982 obj_decoded, tail = obj_expled.decode(
6983 obj_expled_encoded + tail_junk,
6987 self.assertDictEqual(ctx_copied, ctx_dummy)
6989 list(obj_decoded.pps())
6990 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6991 self.assertEqual(tail, tail_junk)
6992 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6993 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6994 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6995 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6997 obj_decoded.expl_llen,
6998 len(len_encode(len(obj_encoded))),
7000 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
7001 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
7004 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
7006 self.assertEqual(obj_decoded.expl_offset, offset)
7007 for obj_inner in obj_decoded:
7008 self.assertIn(obj_inner, obj_decoded)
7009 self.assertSequenceEqual(
7012 obj_inner.offset - offset:
7013 obj_inner.offset + obj_inner.tlvlen - offset
7017 t, _, lv = tag_strip(obj_encoded)
7018 _, _, v = len_decode(lv)
7019 obj_encoded_lenindef = t + LENINDEF + v + EOC
7020 with self.assertRaises(DecodeError):
7021 obj.decode(obj_encoded_lenindef)
7022 obj_decoded_lenindef, tail_lenindef = obj.decode(
7023 obj_encoded_lenindef + tail_junk,
7024 ctx={"bered": True},
7026 self.assertTrue(obj_decoded_lenindef.lenindef)
7027 self.assertTrue(obj_decoded_lenindef.bered)
7028 obj_decoded_lenindef = copy(obj_decoded_lenindef)
7029 self.assertTrue(obj_decoded_lenindef.lenindef)
7030 self.assertTrue(obj_decoded_lenindef.bered)
7031 repr(obj_decoded_lenindef)
7032 list(obj_decoded_lenindef.pps())
7033 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
7034 self.assertEqual(tail_lenindef, tail_junk)
7035 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
7036 with self.assertRaises(DecodeError):
7037 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
7038 with self.assertRaises(DecodeError):
7039 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
7041 evgens = list(obj.decode_evgen(
7042 obj_encoded_lenindef + tail_junk,
7043 decode_path=decode_path,
7044 ctx={"bered": True},
7046 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
7047 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
7048 self.assertEqual(_decode_path, decode_path + (str(i),))
7051 _decode_path, obj, tail = evgens[-1]
7052 self.assertEqual(_decode_path, decode_path)
7056 assert_exceeding_data(
7058 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
7062 def test_bered(self):
7063 class SeqOf(self.base_klass):
7065 encoded = Boolean(False).encode()
7066 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
7067 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7068 with self.assertRaises(DecodeError):
7069 SeqOf().decode(encoded)
7070 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7071 self.assertFalse(decoded.ber_encoded)
7072 self.assertFalse(decoded.lenindef)
7073 self.assertTrue(decoded.bered)
7074 decoded = copy(decoded)
7075 self.assertFalse(decoded.ber_encoded)
7076 self.assertFalse(decoded.lenindef)
7077 self.assertTrue(decoded.bered)
7079 class SeqOf(self.base_klass):
7080 schema = OctetString()
7081 encoded = OctetString(b"whatever").encode()
7083 tag_encode(form=TagFormConstructed, num=4) +
7085 OctetString(b"whatever").encode() +
7088 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7089 with self.assertRaises(DecodeError):
7090 SeqOf().decode(encoded)
7091 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7092 self.assertFalse(decoded.ber_encoded)
7093 self.assertFalse(decoded.lenindef)
7094 self.assertTrue(decoded.bered)
7095 decoded = copy(decoded)
7096 self.assertFalse(decoded.ber_encoded)
7097 self.assertFalse(decoded.lenindef)
7098 self.assertTrue(decoded.bered)
7101 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7102 class SeqOf(SequenceOf):
7106 def _test_symmetric_compare_objs(self, obj1, obj2):
7107 self.assertEqual(obj1, obj2)
7108 self.assertSequenceEqual(list(obj1), list(obj2))
7110 def test_iterator_pickling(self):
7111 class SeqOf(SequenceOf):
7113 register_class(SeqOf)
7116 seqof = seqof(iter(six_xrange(10)))
7117 with assertRaisesRegex(self, ValueError, "iterator"):
7120 def test_iterator_bounds(self):
7121 class SeqOf(SequenceOf):
7127 for i in six_xrange(n):
7130 seqof = SeqOf(gen(n))
7131 self.assertTrue(seqof.ready)
7132 with self.assertRaises(BoundsError):
7134 self.assertFalse(seqof.ready)
7135 seqof = seqof(gen(n))
7136 self.assertTrue(seqof.ready)
7137 with self.assertRaises(BoundsError):
7139 self.assertFalse(seqof.ready)
7141 def test_iterator_twice(self):
7142 class SeqOf(SequenceOf):
7144 bounds = (1, float("+inf"))
7147 for i in six_xrange(10):
7149 seqof = SeqOf(gen())
7150 self.assertTrue(seqof.ready)
7152 self.assertFalse(seqof.ready)
7153 register_class(SeqOf)
7156 def test_iterator_2pass(self):
7157 class SeqOf(SequenceOf):
7159 bounds = (1, float("+inf"))
7162 for i in six_xrange(10):
7164 seqof = SeqOf(gen())
7165 self.assertTrue(seqof.ready)
7166 _, state = seqof.encode1st()
7167 self.assertFalse(seqof.ready)
7168 seqof = seqof(gen())
7169 self.assertTrue(seqof.ready)
7171 seqof.encode2nd(buf.write, iter(state))
7172 self.assertSequenceEqual(
7173 [int(i) for i in seqof.decod(buf.getvalue())],
7177 def test_non_ready_bound_min(self):
7178 class SeqOf(SequenceOf):
7180 bounds = (1, float("+inf"))
7182 self.assertFalse(seqof.ready)
7185 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7190 def _test_symmetric_compare_objs(self, obj1, obj2):
7191 self.assertSetEqual(
7192 set(int(v) for v in obj1),
7193 set(int(v) for v in obj2),
7196 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7197 @given(data_strategy())
7198 def test_sorted(self, d):
7199 values = [OctetString(v) for v in d.draw(lists(binary()))]
7202 schema = OctetString()
7204 seq_encoded = seq.encode()
7205 seq_decoded, _ = seq.decode(seq_encoded)
7206 self.assertSequenceEqual(
7207 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7208 b"".join(sorted([v.encode() for v in values])),
7211 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7212 @given(data_strategy())
7213 def test_unsorted(self, d):
7214 values = [OctetString(v).encode() for v in d.draw(sets(
7215 binary(min_size=1, max_size=5),
7219 values = d.draw(permutations(values))
7220 assume(values != sorted(values))
7221 encoded = b"".join(values)
7222 seq_encoded = b"".join((
7224 len_encode(len(encoded)),
7229 schema = OctetString()
7231 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7232 seq.decode(seq_encoded)
7234 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7235 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7236 self.assertTrue(seq_decoded.ber_encoded)
7237 self.assertTrue(seq_decoded.bered)
7238 seq_decoded = copy(seq_decoded)
7239 self.assertTrue(seq_decoded.ber_encoded)
7240 self.assertTrue(seq_decoded.bered)
7241 self.assertSequenceEqual(
7242 [obj.encode() for obj in seq_decoded],
7247 class TestGoMarshalVectors(TestCase):
7249 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7250 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7251 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7252 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7253 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7255 class Seq(Sequence):
7257 ("erste", Integer()),
7258 ("zweite", Integer(optional=True))
7261 seq["erste"] = Integer(64)
7262 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7263 seq["erste"] = Integer(0x123456)
7264 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7265 seq["erste"] = Integer(64)
7266 seq["zweite"] = Integer(65)
7267 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7269 class NestedSeq(Sequence):
7273 seq["erste"] = Integer(127)
7274 seq["zweite"] = None
7275 nested = NestedSeq()
7276 nested["nest"] = seq
7277 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7279 self.assertSequenceEqual(
7280 OctetString(b"\x01\x02\x03").encode(),
7281 hexdec("0403010203"),
7284 class Seq(Sequence):
7286 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7289 seq["erste"] = Integer(64)
7290 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7292 class Seq(Sequence):
7294 ("erste", Integer(expl=tag_ctxc(5))),
7297 seq["erste"] = Integer(64)
7298 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7300 class Seq(Sequence):
7303 impl=tag_encode(0, klass=TagClassContext),
7308 seq["erste"] = Null()
7309 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7311 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7313 self.assertSequenceEqual(
7314 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7315 hexdec("170d3730303130313030303030305a"),
7317 self.assertSequenceEqual(
7318 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7319 hexdec("170d3039313131353232353631365a"),
7321 self.assertSequenceEqual(
7322 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7323 hexdec("180f32313030303430353132303130315a"),
7326 class Seq(Sequence):
7328 ("erste", GeneralizedTime()),
7331 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7332 self.assertSequenceEqual(
7334 hexdec("3011180f32303039313131353232353631365a"),
7337 self.assertSequenceEqual(
7338 BitString((1, b"\x80")).encode(),
7341 self.assertSequenceEqual(
7342 BitString((12, b"\x81\xF0")).encode(),
7343 hexdec("03030481f0"),
7346 self.assertSequenceEqual(
7347 ObjectIdentifier("1.2.3.4").encode(),
7348 hexdec("06032a0304"),
7350 self.assertSequenceEqual(
7351 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7352 hexdec("06092a864888932d010105"),
7354 self.assertSequenceEqual(
7355 ObjectIdentifier("2.100.3").encode(),
7356 hexdec("0603813403"),
7359 self.assertSequenceEqual(
7360 PrintableString("test").encode(),
7361 hexdec("130474657374"),
7363 self.assertSequenceEqual(
7364 PrintableString("x" * 127).encode(),
7365 hexdec("137F" + "78" * 127),
7367 self.assertSequenceEqual(
7368 PrintableString("x" * 128).encode(),
7369 hexdec("138180" + "78" * 128),
7371 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7373 class Seq(Sequence):
7375 ("erste", IA5String()),
7378 seq["erste"] = IA5String("test")
7379 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7381 class Seq(Sequence):
7383 ("erste", PrintableString()),
7386 seq["erste"] = PrintableString("test")
7387 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7388 # Asterisk is actually not allowable
7389 PrintableString._allowable_chars |= set(b"*")
7390 seq["erste"] = PrintableString("test*")
7391 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7392 PrintableString._allowable_chars -= set(b"*")
7394 class Seq(Sequence):
7396 ("erste", Any(optional=True)),
7397 ("zweite", Integer()),
7400 seq["zweite"] = Integer(64)
7401 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7406 seq.append(Integer(10))
7407 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7409 class _SeqOf(SequenceOf):
7410 schema = PrintableString()
7412 class SeqOf(SequenceOf):
7415 _seqof.append(PrintableString("1"))
7417 seqof.append(_seqof)
7418 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7420 class Seq(Sequence):
7422 ("erste", Integer(default=1)),
7425 seq["erste"] = Integer(0)
7426 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7427 seq["erste"] = Integer(1)
7428 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7429 seq["erste"] = Integer(2)
7430 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7433 class TestPP(TestCase):
7434 @given(data_strategy())
7435 def test_oid_printing(self, d):
7437 str(ObjectIdentifier(k)): v * 2
7438 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7440 chosen = d.draw(sampled_from(sorted(oids)))
7441 chosen_id = oids[chosen]
7442 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7443 self.assertNotIn(chosen_id, pp_console_row(pp))
7446 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7450 class TestAutoAddSlots(TestCase):
7452 class Inher(Integer):
7455 with self.assertRaises(AttributeError):
7457 inher.unexistent = "whatever"
7460 class TestOIDDefines(TestCase):
7461 @given(data_strategy())
7462 def runTest(self, d):
7463 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7464 value_name_chosen = d.draw(sampled_from(value_names))
7466 ObjectIdentifier(oid)
7467 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7469 oid_chosen = d.draw(sampled_from(oids))
7470 values = d.draw(lists(
7472 min_size=len(value_names),
7473 max_size=len(value_names),
7475 for definable_class in (Any, OctetString, BitString):
7477 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7478 oid: Integer() for oid in oids[:-1]
7481 for i, value_name in enumerate(value_names):
7482 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7484 class Seq(Sequence):
7487 for value_name, value in zip(value_names, values):
7488 seq[value_name] = definable_class(Integer(value).encode())
7489 seq["type"] = oid_chosen
7490 seq, _ = Seq().decode(seq.encode())
7491 for value_name in value_names:
7492 if value_name == value_name_chosen:
7494 self.assertIsNone(seq[value_name].defined)
7495 if value_name_chosen in oids[:-1]:
7496 self.assertIsNotNone(seq[value_name_chosen].defined)
7497 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7498 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7501 pprint(seq, big_blobs=True, with_decode_path=True)
7504 class TestDefinesByPath(TestCase):
7505 def test_generated(self):
7506 class Seq(Sequence):
7508 ("type", ObjectIdentifier()),
7509 ("value", OctetString(expl=tag_ctxc(123))),
7512 class SeqInner(Sequence):
7514 ("typeInner", ObjectIdentifier()),
7515 ("valueInner", Any()),
7518 class PairValue(SetOf):
7521 class Pair(Sequence):
7523 ("type", ObjectIdentifier()),
7524 ("value", PairValue()),
7527 class Pairs(SequenceOf):
7534 type_octet_stringed,
7536 ObjectIdentifier(oid)
7537 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7539 seq_integered = Seq()
7540 seq_integered["type"] = type_integered
7541 seq_integered["value"] = OctetString(Integer(123).encode())
7542 seq_integered_raw = seq_integered.encode()
7546 (type_octet_stringed, OctetString(b"whatever")),
7547 (type_integered, Integer(123)),
7548 (type_octet_stringed, OctetString(b"whenever")),
7549 (type_integered, Integer(234)),
7551 for t, v in pairs_input:
7554 ("value", PairValue((Any(v),))),
7556 seq_inner = SeqInner()
7557 seq_inner["typeInner"] = type_innered
7558 seq_inner["valueInner"] = Any(pairs)
7559 seq_sequenced = Seq()
7560 seq_sequenced["type"] = type_sequenced
7561 seq_sequenced["value"] = OctetString(seq_inner.encode())
7562 seq_sequenced_raw = seq_sequenced.encode()
7564 list(seq_sequenced.pps())
7565 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7567 defines_by_path = []
7568 ctx_copied = deepcopy(ctx_dummy)
7569 seq_integered, _ = Seq().decode(
7573 self.assertDictEqual(ctx_copied, ctx_dummy)
7574 self.assertIsNone(seq_integered["value"].defined)
7575 defines_by_path.append(
7576 (("type",), ((("value",), {
7577 type_integered: Integer(),
7578 type_sequenced: SeqInner(),
7581 ctx_copied["defines_by_path"] = defines_by_path
7582 seq_integered, _ = Seq().decode(
7586 del ctx_copied["defines_by_path"]
7587 self.assertDictEqual(ctx_copied, ctx_dummy)
7588 self.assertIsNotNone(seq_integered["value"].defined)
7589 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7590 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7591 self.assertTrue(seq_integered_raw[
7592 seq_integered["value"].defined[1].offset:
7593 ].startswith(Integer(123).encode()))
7595 list(seq_integered.pps())
7596 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7598 ctx_copied["defines_by_path"] = defines_by_path
7599 seq_sequenced, _ = Seq().decode(
7603 del ctx_copied["defines_by_path"]
7604 self.assertDictEqual(ctx_copied, ctx_dummy)
7605 self.assertIsNotNone(seq_sequenced["value"].defined)
7606 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7607 seq_inner = seq_sequenced["value"].defined[1]
7608 self.assertIsNone(seq_inner["valueInner"].defined)
7610 list(seq_sequenced.pps())
7611 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7613 defines_by_path.append((
7614 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7615 ((("valueInner",), {type_innered: Pairs()}),),
7617 ctx_copied["defines_by_path"] = defines_by_path
7618 seq_sequenced, _ = Seq().decode(
7622 del ctx_copied["defines_by_path"]
7623 self.assertDictEqual(ctx_copied, ctx_dummy)
7624 self.assertIsNotNone(seq_sequenced["value"].defined)
7625 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7626 seq_inner = seq_sequenced["value"].defined[1]
7627 self.assertIsNotNone(seq_inner["valueInner"].defined)
7628 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7629 pairs = seq_inner["valueInner"].defined[1]
7631 self.assertIsNone(pair["value"][0].defined)
7633 list(seq_sequenced.pps())
7634 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7636 defines_by_path.append((
7639 DecodePathDefBy(type_sequenced),
7641 DecodePathDefBy(type_innered),
7646 type_integered: Integer(),
7647 type_octet_stringed: OctetString(),
7650 ctx_copied["defines_by_path"] = defines_by_path
7651 seq_sequenced, _ = Seq().decode(
7655 del ctx_copied["defines_by_path"]
7656 self.assertDictEqual(ctx_copied, ctx_dummy)
7657 self.assertIsNotNone(seq_sequenced["value"].defined)
7658 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7659 seq_inner = seq_sequenced["value"].defined[1]
7660 self.assertIsNotNone(seq_inner["valueInner"].defined)
7661 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7662 pairs_got = seq_inner["valueInner"].defined[1]
7663 for pair_input, pair_got in zip(pairs_input, pairs_got):
7664 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7665 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7667 list(seq_sequenced.pps())
7668 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7670 @given(oid_strategy(), integers())
7671 def test_simple(self, oid, tgt):
7672 class Inner(Sequence):
7674 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7675 ObjectIdentifier(oid): Integer(),
7679 class Outer(Sequence):
7682 ("tgt", OctetString()),
7686 inner["oid"] = ObjectIdentifier(oid)
7688 outer["inner"] = inner
7689 outer["tgt"] = OctetString(Integer(tgt).encode())
7690 decoded, _ = Outer().decode(outer.encode())
7691 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7693 def test_remaining_data(self):
7694 oid = ObjectIdentifier("1.2.3")
7696 class Seq(Sequence):
7698 ("oid", ObjectIdentifier(defines=((("tgt",), {
7701 ("tgt", OctetString()),
7706 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7708 with assertRaisesRegex(self, DecodeError, "remaining data"):
7709 Seq().decode(seq.encode())
7711 def test_remaining_data_seqof(self):
7712 oid = ObjectIdentifier("1.2.3")
7715 schema = OctetString()
7717 class Seq(Sequence):
7719 ("oid", ObjectIdentifier(defines=((("tgt",), {
7727 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7729 with assertRaisesRegex(self, DecodeError, "remaining data"):
7730 Seq().decode(seq.encode())
7733 class TestAbsDecodePath(TestCase):
7735 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7736 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7738 def test_concat(self, decode_path, rel_path):
7739 dp = abs_decode_path(decode_path, rel_path)
7740 self.assertSequenceEqual(dp, decode_path + rel_path)
7744 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7745 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7747 def test_abs(self, decode_path, rel_path):
7748 self.assertSequenceEqual(
7749 abs_decode_path(decode_path, ("/",) + rel_path),
7754 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7755 integers(min_value=1, max_value=3),
7756 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7758 def test_dots(self, decode_path, number_of_dots, rel_path):
7759 self.assertSequenceEqual(
7760 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7761 decode_path[:-number_of_dots] + rel_path,
7765 class TestStrictDefaultExistence(TestCase):
7766 @given(data_strategy())
7767 def runTest(self, d):
7768 count = d.draw(integers(min_value=1, max_value=10))
7769 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7771 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7772 for i in range(count)
7774 for klass in (Sequence, Set):
7778 for i in range(count):
7779 seq["int%d" % i] = Integer(123)
7781 chosen_choice = "int%d" % chosen
7782 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7783 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7785 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7786 self.assertTrue(decoded.ber_encoded)
7787 self.assertTrue(decoded.bered)
7788 decoded = copy(decoded)
7789 self.assertTrue(decoded.ber_encoded)
7790 self.assertTrue(decoded.bered)
7791 decoded, _ = seq.decode(raw, ctx={"bered": True})
7792 self.assertTrue(decoded.ber_encoded)
7793 self.assertTrue(decoded.bered)
7794 decoded = copy(decoded)
7795 self.assertTrue(decoded.ber_encoded)
7796 self.assertTrue(decoded.bered)
7799 class TestX690PrefixedType(TestCase):
7801 self.assertSequenceEqual(
7802 VisibleString("Jones").encode(),
7803 hexdec("1A054A6F6E6573"),
7807 self.assertSequenceEqual(
7810 impl=tag_encode(3, klass=TagClassApplication),
7812 hexdec("43054A6F6E6573"),
7816 self.assertSequenceEqual(
7820 impl=tag_encode(3, klass=TagClassApplication),
7824 hexdec("A20743054A6F6E6573"),
7828 self.assertSequenceEqual(
7832 impl=tag_encode(3, klass=TagClassApplication),
7834 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7836 hexdec("670743054A6F6E6573"),
7840 self.assertSequenceEqual(
7841 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7842 hexdec("82054A6F6E6573"),
7846 class TestExplOOB(TestCase):
7848 expl = tag_ctxc(123)
7849 raw = Integer(123).encode() + Integer(234).encode()
7850 raw = b"".join((expl, len_encode(len(raw)), raw))
7851 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7852 Integer(expl=expl).decode(raw)
7853 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7856 class TestPickleDifferentVersion(TestCase):
7858 pickled = pickle_dumps(Integer(123), pickle_proto)
7860 version_orig = pyderasn.__version__
7861 pyderasn.__version__ += "different"
7862 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7863 pickle_loads(pickled)
7864 pyderasn.__version__ = version_orig
7865 pickle_loads(pickled)
7868 class TestCERSetOrdering(TestCase):
7869 def test_vectors(self):
7870 """Taken from X.690-201508
7874 ("c", Integer(impl=tag_ctxp(2))),
7875 ("d", Integer(impl=tag_ctxp(4))),
7880 ("g", Integer(impl=tag_ctxp(5))),
7881 ("h", Integer(impl=tag_ctxp(6))),
7886 ("j", Integer(impl=tag_ctxp(0))),
7897 ("a", Integer(impl=tag_ctxp(3))),
7898 ("b", B(expl=tag_ctxc(1))),
7903 ("a", Integer(123)),
7904 ("b", B(("d", Integer(234)))),
7905 ("e", E(("f", F(("g", Integer(345)))))),
7907 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7908 self.assertSequenceEqual(
7909 [i.__class__.__name__ for i in order],
7910 ("E", "B", "Integer"),