2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2020 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this program. If not, see
16 # <http://www.gnu.org/licenses/>.
19 from copy import deepcopy
20 from datetime import datetime
21 from datetime import timedelta
22 from importlib import import_module
23 from io import BytesIO
24 from operator import attrgetter
25 from os import environ
26 from os import urandom
27 from random import random
28 from string import ascii_letters
29 from string import digits
30 from string import printable
31 from string import whitespace
32 from time import mktime
34 from unittest import TestCase
36 from 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_x690_vector(self):
3087 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3088 ObjectIdentifier((2, 999, 3)),
3091 def test_nonnormalized_first_arc(self):
3093 ObjectIdentifier.tag_default +
3096 ObjectIdentifier((1, 0)).encode()[-1:]
3098 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3099 self.assertTrue(obj.ber_encoded)
3100 self.assertTrue(obj.bered)
3102 self.assertTrue(obj.ber_encoded)
3103 self.assertTrue(obj.bered)
3104 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3105 ObjectIdentifier().decode(tampered)
3107 @given(data_strategy())
3108 def test_negative_arcs(self, d):
3109 oid = list(d.draw(oid_strategy()))
3112 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3114 if oid[idx - 1] == 0:
3116 with self.assertRaises(InvalidOID):
3117 ObjectIdentifier(tuple(oid))
3118 with self.assertRaises(InvalidOID):
3119 ObjectIdentifier(".".join(str(i) for i in oid))
3121 @given(data_strategy())
3122 def test_plused_arcs(self, d):
3123 oid = [str(arc) for arc in d.draw(oid_strategy())]
3124 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3125 oid[idx - 1] = "+" + oid[idx - 1]
3126 with self.assertRaises(InvalidOID):
3127 ObjectIdentifier(".".join(str(i) for i in oid))
3129 @given(data_strategy())
3130 def test_nonnormalized_arcs(self, d):
3131 arcs = d.draw(lists(
3132 integers(min_value=0, max_value=100),
3136 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3137 _, _, lv = tag_strip(dered)
3138 _, _, v = len_decode(lv)
3139 v_no_first_arc = v[1:]
3140 idx_for_tamper = d.draw(integers(
3142 max_value=len(v_no_first_arc) - 1,
3144 tampered = list(bytearray(v_no_first_arc))
3145 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3146 tampered.insert(idx_for_tamper, 0x80)
3147 tampered = bytes(bytearray(tampered))
3149 ObjectIdentifier.tag_default +
3150 len_encode(len(tampered)) +
3153 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3154 self.assertTrue(obj.ber_encoded)
3155 self.assertTrue(obj.bered)
3157 self.assertTrue(obj.ber_encoded)
3158 self.assertTrue(obj.bered)
3159 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3160 ObjectIdentifier().decode(tampered)
3164 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3166 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3167 values = list(draw(sets(
3169 min_size=len(schema),
3170 max_size=len(schema),
3172 schema = list(zip(schema, values))
3173 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3177 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3179 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3180 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3181 optional = draw(one_of(none(), booleans()))
3183 draw(integers(min_value=0)),
3184 draw(integers(min_value=0)),
3185 draw(integers(min_value=0)),
3187 return (schema, value, impl, expl, default, optional, _decoded)
3190 class TestEnumerated(CommonMixin, TestCase):
3191 class EWhatever(Enumerated):
3192 schema = (("whatever", 0),)
3194 base_klass = EWhatever
3196 def test_schema_required(self):
3197 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3200 def test_invalid_value_type(self):
3201 with self.assertRaises(InvalidValueType) as err:
3202 self.base_klass((1, 2))
3205 @given(sets(text_letters(), min_size=2))
3206 def test_unknown_name(self, schema_input):
3207 missing = schema_input.pop()
3209 class E(Enumerated):
3210 schema = [(n, 123) for n in schema_input]
3211 with self.assertRaises(ObjUnknown) as err:
3216 sets(text_letters(), min_size=2),
3217 sets(integers(), min_size=2),
3219 def test_unknown_value(self, schema_input, values_input):
3221 missing_value = values_input.pop()
3222 _input = list(zip(schema_input, values_input))
3224 class E(Enumerated):
3226 with self.assertRaises(DecodeError) as err:
3231 def test_optional(self, optional):
3232 obj = self.base_klass(default="whatever", optional=optional)
3233 self.assertTrue(obj.optional)
3235 def test_ready(self):
3236 obj = self.base_klass()
3237 self.assertFalse(obj.ready)
3240 pprint(obj, big_blobs=True, with_decode_path=True)
3241 with self.assertRaises(ObjNotReady) as err:
3244 obj = self.base_klass("whatever")
3245 self.assertTrue(obj.ready)
3248 pprint(obj, big_blobs=True, with_decode_path=True)
3250 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3251 def test_comparison(self, value1, value2, tag1, tag2):
3252 class E(Enumerated):
3254 ("whatever0", value1),
3255 ("whatever1", value2),
3258 class EInherited(E):
3260 for klass in (E, EInherited):
3261 obj1 = klass(value1)
3262 obj2 = klass(value2)
3263 self.assertEqual(obj1 == obj2, value1 == value2)
3264 self.assertEqual(obj1 != obj2, value1 != value2)
3265 self.assertEqual(obj1 == int(obj2), value1 == value2)
3266 obj1 = klass(value1, impl=tag1)
3267 obj2 = klass(value1, impl=tag2)
3268 self.assertEqual(obj1 == obj2, tag1 == tag2)
3269 self.assertEqual(obj1 != obj2, tag1 != tag2)
3271 @given(data_strategy())
3272 def test_call(self, d):
3281 ) = d.draw(enumerated_values_strategy())
3283 class E(Enumerated):
3284 schema = schema_initial
3286 value=value_initial,
3289 default=default_initial,
3290 optional=optional_initial or False,
3291 _decoded=_decoded_initial,
3301 ) = d.draw(enumerated_values_strategy(
3302 schema=schema_initial,
3303 do_expl=impl_initial is None,
3313 value_expected = default if value is None else value
3315 default_initial if value_expected is None
3320 dict(schema_initial).get(value_expected, value_expected),
3322 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3323 self.assertEqual(obj.expl_tag, expl or expl_initial)
3326 default_initial if default is None else default,
3328 if obj.default is None:
3329 optional = optional_initial if optional is None else optional
3330 optional = False if optional is None else optional
3333 self.assertEqual(obj.optional, optional)
3334 self.assertEqual(obj.specs, dict(schema_initial))
3336 @given(enumerated_values_strategy())
3337 def test_copy(self, values):
3338 schema_input, value, impl, expl, default, optional, _decoded = values
3340 class E(Enumerated):
3341 schema = schema_input
3351 for copy_func in copy_funcs:
3352 obj_copied = copy_func(obj)
3353 self.assert_copied_basic_fields(obj, obj_copied)
3354 self.assertEqual(obj.specs, obj_copied.specs)
3356 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3357 @given(data_strategy())
3358 def test_symmetric(self, d):
3359 schema_input, _, _, _, default, optional, _decoded = d.draw(
3360 enumerated_values_strategy(),
3362 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3363 offset = d.draw(integers(min_value=0))
3364 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3365 tail_junk = d.draw(binary(max_size=5))
3366 decode_path = d.draw(decode_path_strat)
3368 class E(Enumerated):
3369 schema = schema_input
3378 pprint(obj, big_blobs=True, with_decode_path=True)
3379 self.assertFalse(obj.expled)
3380 obj_encoded = obj.encode()
3381 self.assertEqual(encode2pass(obj), obj_encoded)
3382 obj_expled = obj(value, expl=tag_expl)
3383 self.assertTrue(obj_expled.expled)
3385 list(obj_expled.pps())
3386 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3387 obj_expled_encoded = obj_expled.encode()
3388 ctx_copied = deepcopy(ctx_dummy)
3389 obj_decoded, tail = obj_expled.decode(
3390 obj_expled_encoded + tail_junk,
3394 self.assertDictEqual(ctx_copied, ctx_dummy)
3396 list(obj_decoded.pps())
3397 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3398 self.assertEqual(tail, tail_junk)
3399 self.assertEqual(obj_decoded, obj_expled)
3400 self.assertNotEqual(obj_decoded, obj)
3401 self.assertEqual(int(obj_decoded), int(obj_expled))
3402 self.assertEqual(int(obj_decoded), int(obj))
3403 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3404 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3405 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3407 obj_decoded.expl_llen,
3408 len(len_encode(len(obj_encoded))),
3410 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3411 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3414 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3416 self.assertEqual(obj_decoded.expl_offset, offset)
3417 assert_exceeding_data(
3419 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3423 evgens = list(obj_expled.decode_evgen(
3424 obj_expled_encoded + tail_junk,
3426 decode_path=decode_path,
3429 self.assertEqual(len(evgens), 1)
3430 _decode_path, obj, tail = evgens[0]
3431 self.assertSequenceEqual(tail, tail_junk)
3432 self.assertEqual(_decode_path, decode_path)
3433 self.assertEqual(obj, obj_decoded)
3434 self.assertEqual(obj.expl_offset, offset)
3440 def string_values_strategy(draw, alphabet, do_expl=False):
3441 bound_min, bound_max = sorted(draw(sets(
3442 integers(min_value=0, max_value=1 << 7),
3446 value = draw(one_of(
3448 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3450 default = draw(one_of(
3452 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3455 if draw(booleans()):
3456 bounds = (bound_min, bound_max)
3460 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3462 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3463 optional = draw(one_of(none(), booleans()))
3465 draw(integers(min_value=0)),
3466 draw(integers(min_value=0)),
3467 draw(integers(min_value=0)),
3469 return (value, bounds, impl, expl, default, optional, _decoded)
3472 class StringMixin(object):
3473 def test_invalid_value_type(self):
3474 with self.assertRaises(InvalidValueType) as err:
3475 self.base_klass((1, 2))
3478 def text_alphabet(self):
3479 return "".join(six_unichr(c) for c in six_xrange(256))
3482 def test_optional(self, optional):
3483 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3484 self.assertTrue(obj.optional)
3486 @given(data_strategy())
3487 def test_ready(self, d):
3488 obj = self.base_klass()
3489 self.assertFalse(obj.ready)
3492 pprint(obj, big_blobs=True, with_decode_path=True)
3494 with self.assertRaises(ObjNotReady) as err:
3497 with self.assertRaises(ObjNotReady) as err:
3499 value = d.draw(text(alphabet=self.text_alphabet()))
3500 obj = self.base_klass(value)
3501 self.assertTrue(obj.ready)
3504 pprint(obj, big_blobs=True, with_decode_path=True)
3507 @given(data_strategy())
3508 def test_comparison(self, d):
3509 value1 = d.draw(text(alphabet=self.text_alphabet()))
3510 value2 = d.draw(text(alphabet=self.text_alphabet()))
3511 tag1 = d.draw(binary(min_size=1))
3512 tag2 = d.draw(binary(min_size=1))
3513 obj1 = self.base_klass(value1)
3514 obj2 = self.base_klass(value2)
3515 self.assertEqual(obj1 == obj2, value1 == value2)
3516 self.assertEqual(obj1 != obj2, value1 != value2)
3517 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3518 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3519 obj1 = self.base_klass(value1, impl=tag1)
3520 obj2 = self.base_klass(value1, impl=tag2)
3521 self.assertEqual(obj1 == obj2, tag1 == tag2)
3522 self.assertEqual(obj1 != obj2, tag1 != tag2)
3524 @given(data_strategy())
3525 def test_bounds_satisfied(self, d):
3526 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3527 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3528 value = d.draw(text(
3529 alphabet=self.text_alphabet(),
3533 self.base_klass(value=value, bounds=(bound_min, bound_max))
3535 @given(data_strategy())
3536 def test_bounds_unsatisfied(self, d):
3537 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3538 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3539 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3540 with self.assertRaises(BoundsError) as err:
3541 self.base_klass(value=value, bounds=(bound_min, bound_max))
3543 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3544 self.base_klass(bounds=(bound_min, bound_max)).decode(
3545 self.base_klass(value).encode()
3548 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3549 self.base_klass(bounds=(bound_min, bound_max)).decode(
3550 encode2pass(self.base_klass(value))
3552 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3553 with self.assertRaises(BoundsError) as err:
3554 self.base_klass(value=value, bounds=(bound_min, bound_max))
3556 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3557 self.base_klass(bounds=(bound_min, bound_max)).decode(
3558 self.base_klass(value).encode()
3561 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3562 self.base_klass(bounds=(bound_min, bound_max)).decode(
3563 encode2pass(self.base_klass(value))
3566 @given(data_strategy())
3567 def test_call(self, d):
3576 ) = d.draw(string_values_strategy(self.text_alphabet()))
3577 obj_initial = self.base_klass(
3583 optional_initial or False,
3594 ) = d.draw(string_values_strategy(
3595 self.text_alphabet(),
3596 do_expl=impl_initial is None,
3598 if (default is None) and (obj_initial.default is not None):
3601 (bounds is None) and
3602 (value is not None) and
3603 (bounds_initial is not None) and
3604 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3608 (bounds is None) and
3609 (default is not None) and
3610 (bounds_initial is not None) and
3611 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3614 obj = obj_initial(value, bounds, impl, expl, default, optional)
3616 value_expected = default if value is None else value
3618 default_initial if value_expected is None
3621 self.assertEqual(obj, value_expected)
3622 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3623 self.assertEqual(obj.expl_tag, expl or expl_initial)
3626 default_initial if default is None else default,
3628 if obj.default is None:
3629 optional = optional_initial if optional is None else optional
3630 optional = False if optional is None else optional
3633 self.assertEqual(obj.optional, optional)
3635 (obj._bound_min, obj._bound_max),
3636 bounds or bounds_initial or (0, float("+inf")),
3639 @given(data_strategy())
3640 def test_copy(self, d):
3641 values = d.draw(string_values_strategy(self.text_alphabet()))
3642 obj = self.base_klass(*values)
3643 for copy_func in copy_funcs:
3644 obj_copied = copy_func(obj)
3645 self.assert_copied_basic_fields(obj, obj_copied)
3646 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3647 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3648 self.assertEqual(obj._value, obj_copied._value)
3650 @given(data_strategy())
3651 def test_stripped(self, d):
3652 value = d.draw(text(alphabet=self.text_alphabet()))
3653 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3654 obj = self.base_klass(value, impl=tag_impl)
3655 with self.assertRaises(NotEnoughData):
3656 obj.decode(obj.encode()[:-1])
3658 @given(data_strategy())
3659 def test_stripped_expl(self, d):
3660 value = d.draw(text(alphabet=self.text_alphabet()))
3661 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3662 obj = self.base_klass(value, expl=tag_expl)
3663 with self.assertRaises(NotEnoughData):
3664 obj.decode(obj.encode()[:-1])
3667 integers(min_value=31),
3668 integers(min_value=0),
3671 def test_bad_tag(self, tag, offset, decode_path):
3672 with self.assertRaises(DecodeError) as err:
3673 self.base_klass().decode(
3674 tag_encode(tag)[:-1],
3676 decode_path=decode_path,
3679 self.assertEqual(err.exception.offset, offset)
3680 self.assertEqual(err.exception.decode_path, decode_path)
3683 integers(min_value=128),
3684 integers(min_value=0),
3687 def test_bad_len(self, l, offset, decode_path):
3688 with self.assertRaises(DecodeError) as err:
3689 self.base_klass().decode(
3690 self.base_klass.tag_default + len_encode(l)[:-1],
3692 decode_path=decode_path,
3695 self.assertEqual(err.exception.offset, offset)
3696 self.assertEqual(err.exception.decode_path, decode_path)
3699 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3700 integers(min_value=0),
3703 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3704 value, bound_min = list(sorted(ints))
3706 class String(self.base_klass):
3707 # Multiply this value by four, to satisfy UTF-32 bounds
3708 # (4 bytes per character) validation
3709 bounds = (bound_min * 4, bound_min * 4)
3710 with self.assertRaises(DecodeError) as err:
3712 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3714 decode_path=decode_path,
3717 self.assertEqual(err.exception.offset, offset)
3718 self.assertEqual(err.exception.decode_path, decode_path)
3720 @given(data_strategy())
3721 def test_symmetric(self, d):
3722 values = d.draw(string_values_strategy(self.text_alphabet()))
3723 value = d.draw(text(alphabet=self.text_alphabet()))
3724 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3725 offset = d.draw(integers(min_value=0))
3726 tail_junk = d.draw(binary(max_size=5))
3727 decode_path = d.draw(decode_path_strat)
3728 _, _, _, _, default, optional, _decoded = values
3729 obj = self.base_klass(
3737 pprint(obj, big_blobs=True, with_decode_path=True)
3738 self.assertFalse(obj.expled)
3739 obj_encoded = obj.encode()
3740 self.assertEqual(encode2pass(obj), obj_encoded)
3741 obj_expled = obj(value, expl=tag_expl)
3742 self.assertTrue(obj_expled.expled)
3744 list(obj_expled.pps())
3745 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3746 obj_expled_encoded = obj_expled.encode()
3747 ctx_copied = deepcopy(ctx_dummy)
3748 obj_decoded, tail = obj_expled.decode(
3749 obj_expled_encoded + tail_junk,
3753 self.assertDictEqual(ctx_copied, ctx_dummy)
3755 list(obj_decoded.pps())
3756 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3757 self.assertEqual(tail, tail_junk)
3758 self.assertEqual(obj_decoded, obj_expled)
3759 self.assertNotEqual(obj_decoded, obj)
3760 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3761 self.assertEqual(bytes(obj_decoded), bytes(obj))
3762 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3763 self.assertEqual(text_type(obj_decoded), text_type(obj))
3764 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3765 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3766 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3768 obj_decoded.expl_llen,
3769 len(len_encode(len(obj_encoded))),
3771 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3772 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3775 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3777 self.assertEqual(obj_decoded.expl_offset, offset)
3778 assert_exceeding_data(
3780 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3784 evgens = list(obj_expled.decode_evgen(
3785 obj_expled_encoded + tail_junk,
3787 decode_path=decode_path,
3790 self.assertEqual(len(evgens), 1)
3791 _decode_path, obj, tail = evgens[0]
3792 self.assertSequenceEqual(tail, tail_junk)
3793 self.assertEqual(_decode_path, decode_path)
3794 if not getattr(self, "evgen_mode_skip_value", True):
3795 self.assertEqual(obj, obj_decoded)
3796 self.assertEqual(obj.expl_offset, offset)
3801 cyrillic_letters = text(
3802 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3808 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3809 base_klass = UTF8String
3811 @given(cyrillic_letters)
3812 def test_byte_per_primitive(self, chars):
3814 char_raw = char.encode("utf-8")
3815 encoded = b"".join((
3816 self.base_klass().tag_constructed,
3818 OctetString(char_raw[:1]).encode(),
3819 OctetString(char_raw[1:2]).encode(),
3823 self.base_klass().decod(encoded, ctx={"bered": True}),
3828 class UnicodeDecodeErrorMixin(object):
3829 @given(cyrillic_letters)
3830 def test_unicode_decode_error(self, cyrillic_text):
3831 with self.assertRaises(DecodeError):
3832 self.base_klass(cyrillic_text)
3835 class TestNumericString(StringMixin, CommonMixin, TestCase):
3836 base_klass = NumericString
3838 def text_alphabet(self):
3841 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3842 def test_non_numeric(self, non_numeric_text):
3843 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3844 self.base_klass(non_numeric_text)
3847 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3848 integers(min_value=0),
3851 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3852 value, bound_min = list(sorted(ints))
3854 class String(self.base_klass):
3855 bounds = (bound_min, bound_min)
3856 with self.assertRaises(DecodeError) as err:
3858 self.base_klass(b"1" * value).encode(),
3860 decode_path=decode_path,
3863 self.assertEqual(err.exception.offset, offset)
3864 self.assertEqual(err.exception.decode_path, decode_path)
3866 def test_byte_per_primitive(self):
3867 encoded = b"".join((
3868 self.base_klass().tag_constructed,
3870 OctetString(b"1").encode(),
3871 OctetString(b"2").encode(),
3875 self.base_klass().decod(encoded, ctx={"bered": True}),
3880 class TestPrintableString(
3881 UnicodeDecodeErrorMixin,
3886 base_klass = PrintableString
3888 def text_alphabet(self):
3889 return ascii_letters + digits + " '()+,-./:=?"
3891 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3892 def test_non_printable(self, non_printable_text):
3893 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3894 self.base_klass(non_printable_text)
3897 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3898 integers(min_value=0),
3901 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3902 value, bound_min = list(sorted(ints))
3904 class String(self.base_klass):
3905 bounds = (bound_min, bound_min)
3906 with self.assertRaises(DecodeError) as err:
3908 self.base_klass(b"1" * value).encode(),
3910 decode_path=decode_path,
3913 self.assertEqual(err.exception.offset, offset)
3914 self.assertEqual(err.exception.decode_path, decode_path)
3916 def test_allowable_invalid_chars(self):
3918 ("*", {"allow_asterisk": True}),
3919 ("&", {"allow_ampersand": True}),
3920 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3923 obj = self.base_klass(s)
3924 for prop in kwargs.keys():
3925 self.assertFalse(getattr(obj, prop))
3927 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3929 self.base_klass(s, **kwargs)
3930 klass = self.base_klass(**kwargs)
3932 for prop in kwargs.keys():
3933 self.assertTrue(getattr(obj, prop))
3936 for prop in kwargs.keys():
3937 self.assertTrue(getattr(obj, prop))
3940 class TestTeletexString(
3941 UnicodeDecodeErrorMixin,
3946 base_klass = TeletexString
3949 class TestVideotexString(
3950 UnicodeDecodeErrorMixin,
3955 base_klass = VideotexString
3958 class TestIA5String(
3959 UnicodeDecodeErrorMixin,
3964 base_klass = IA5String
3966 def text_alphabet(self):
3967 return "".join(six_unichr(c) for c in six_xrange(128))
3969 @given(integers(min_value=128, max_value=255))
3970 def test_alphabet_bad(self, code):
3971 with self.assertRaises(DecodeError):
3972 self.base_klass().decod(
3973 self.base_klass.tag_default +
3975 bytes(bytearray([code])),
3979 class TestGraphicString(
3980 UnicodeDecodeErrorMixin,
3985 base_klass = GraphicString
3988 class TestVisibleString(
3989 UnicodeDecodeErrorMixin,
3994 base_klass = VisibleString
3996 def text_alphabet(self):
3997 return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
3999 def test_x690_vector(self):
4000 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
4001 self.assertSequenceEqual(tail, b"")
4002 self.assertEqual(str(obj), "Jones")
4003 self.assertFalse(obj.ber_encoded)
4004 self.assertFalse(obj.lenindef)
4005 self.assertFalse(obj.bered)
4007 obj, tail = VisibleString().decode(
4008 hexdec("3A0904034A6F6E04026573"),
4009 ctx={"bered": True},
4011 self.assertSequenceEqual(tail, b"")
4012 self.assertEqual(str(obj), "Jones")
4013 self.assertTrue(obj.ber_encoded)
4014 self.assertFalse(obj.lenindef)
4015 self.assertTrue(obj.bered)
4017 self.assertTrue(obj.ber_encoded)
4018 self.assertFalse(obj.lenindef)
4019 self.assertTrue(obj.bered)
4021 obj, tail = VisibleString().decode(
4022 hexdec("3A8004034A6F6E040265730000"),
4023 ctx={"bered": True},
4025 self.assertSequenceEqual(tail, b"")
4026 self.assertEqual(str(obj), "Jones")
4027 self.assertTrue(obj.ber_encoded)
4028 self.assertTrue(obj.lenindef)
4029 self.assertTrue(obj.bered)
4031 self.assertTrue(obj.ber_encoded)
4032 self.assertTrue(obj.lenindef)
4033 self.assertTrue(obj.bered)
4036 integers(min_value=0, max_value=ord(" ") - 1),
4037 integers(min_value=ord("~") + 1, max_value=255),
4039 def test_alphabet_bad(self, code):
4040 with self.assertRaises(DecodeError):
4041 self.base_klass().decod(
4042 self.base_klass.tag_default +
4044 bytes(bytearray([code])),
4048 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
4049 integers(min_value=0),
4052 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
4053 value, bound_min = list(sorted(ints))
4055 class String(self.base_klass):
4056 bounds = (bound_min, bound_min)
4057 with self.assertRaises(DecodeError) as err:
4059 self.base_klass(b"1" * value).encode(),
4061 decode_path=decode_path,
4064 self.assertEqual(err.exception.offset, offset)
4065 self.assertEqual(err.exception.decode_path, decode_path)
4068 class TestGeneralString(
4069 UnicodeDecodeErrorMixin,
4074 base_klass = GeneralString
4077 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4078 base_klass = UniversalString
4081 class TestBMPString(StringMixin, CommonMixin, TestCase):
4082 base_klass = BMPString
4086 def generalized_time_values_strategy(
4094 if draw(booleans()):
4095 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4097 value = value.replace(microsecond=0)
4099 if draw(booleans()):
4100 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4102 default = default.replace(microsecond=0)
4106 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4108 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4109 optional = draw(one_of(none(), booleans()))
4111 draw(integers(min_value=0)),
4112 draw(integers(min_value=0)),
4113 draw(integers(min_value=0)),
4115 return (value, impl, expl, default, optional, _decoded)
4118 class TimeMixin(object):
4119 def test_invalid_value_type(self):
4120 with self.assertRaises(InvalidValueType) as err:
4121 self.base_klass(datetime.now().timetuple())
4124 @given(data_strategy())
4125 def test_optional(self, d):
4126 default = d.draw(datetimes(
4127 min_value=self.min_datetime,
4128 max_value=self.max_datetime,
4130 optional = d.draw(booleans())
4131 obj = self.base_klass(default=default, optional=optional)
4132 self.assertTrue(obj.optional)
4134 @given(data_strategy())
4135 def test_ready(self, d):
4136 obj = self.base_klass()
4137 self.assertFalse(obj.ready)
4140 pprint(obj, big_blobs=True, with_decode_path=True)
4141 with self.assertRaises(ObjNotReady) as err:
4144 with self.assertRaises(ObjNotReady) as err:
4146 value = d.draw(datetimes(
4147 min_value=self.min_datetime,
4148 max_value=self.max_datetime,
4150 obj = self.base_klass(value)
4151 self.assertTrue(obj.ready)
4154 pprint(obj, big_blobs=True, with_decode_path=True)
4156 @given(data_strategy())
4157 def test_comparison(self, d):
4158 value1 = d.draw(datetimes(
4159 min_value=self.min_datetime,
4160 max_value=self.max_datetime,
4162 value2 = d.draw(datetimes(
4163 min_value=self.min_datetime,
4164 max_value=self.max_datetime,
4166 tag1 = d.draw(binary(min_size=1))
4167 tag2 = d.draw(binary(min_size=1))
4169 value1 = value1.replace(microsecond=0)
4170 value2 = value2.replace(microsecond=0)
4171 obj1 = self.base_klass(value1)
4172 obj2 = self.base_klass(value2)
4173 self.assertEqual(obj1 == obj2, value1 == value2)
4174 self.assertEqual(obj1 != obj2, value1 != value2)
4175 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4176 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4177 obj1 = self.base_klass(value1, impl=tag1)
4178 obj2 = self.base_klass(value1, impl=tag2)
4179 self.assertEqual(obj1 == obj2, tag1 == tag2)
4180 self.assertEqual(obj1 != obj2, tag1 != tag2)
4182 @given(data_strategy())
4183 def test_call(self, d):
4191 ) = d.draw(generalized_time_values_strategy(
4192 min_datetime=self.min_datetime,
4193 max_datetime=self.max_datetime,
4194 omit_ms=self.omit_ms,
4196 obj_initial = self.base_klass(
4197 value=value_initial,
4200 default=default_initial,
4201 optional=optional_initial or False,
4202 _decoded=_decoded_initial,
4211 ) = d.draw(generalized_time_values_strategy(
4212 min_datetime=self.min_datetime,
4213 max_datetime=self.max_datetime,
4214 omit_ms=self.omit_ms,
4215 do_expl=impl_initial is None,
4225 value_expected = default if value is None else value
4227 default_initial if value_expected is None
4230 self.assertEqual(obj, value_expected)
4231 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4232 self.assertEqual(obj.expl_tag, expl or expl_initial)
4235 default_initial if default is None else default,
4237 if obj.default is None:
4238 optional = optional_initial if optional is None else optional
4239 optional = False if optional is None else optional
4242 self.assertEqual(obj.optional, optional)
4244 @given(data_strategy())
4245 def test_copy(self, d):
4246 values = d.draw(generalized_time_values_strategy(
4247 min_datetime=self.min_datetime,
4248 max_datetime=self.max_datetime,
4250 obj = self.base_klass(*values)
4251 for copy_func in copy_funcs:
4252 obj_copied = copy_func(obj)
4253 self.assert_copied_basic_fields(obj, obj_copied)
4254 self.assertEqual(obj._value, obj_copied._value)
4256 @given(data_strategy())
4257 def test_stripped(self, d):
4258 value = d.draw(datetimes(
4259 min_value=self.min_datetime,
4260 max_value=self.max_datetime,
4262 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4263 obj = self.base_klass(value, impl=tag_impl)
4264 with self.assertRaises(NotEnoughData):
4265 obj.decode(obj.encode()[:-1])
4267 @given(data_strategy())
4268 def test_stripped_expl(self, d):
4269 value = d.draw(datetimes(
4270 min_value=self.min_datetime,
4271 max_value=self.max_datetime,
4273 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4274 obj = self.base_klass(value, expl=tag_expl)
4275 with self.assertRaises(NotEnoughData):
4276 obj.decode(obj.encode()[:-1])
4278 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4279 @given(data_strategy())
4280 def test_symmetric(self, d):
4281 values = d.draw(generalized_time_values_strategy(
4282 min_datetime=self.min_datetime,
4283 max_datetime=self.max_datetime,
4285 value = d.draw(datetimes(
4286 min_value=self.min_datetime,
4287 max_value=self.max_datetime,
4289 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4290 offset = d.draw(integers(min_value=0))
4291 tail_junk = d.draw(binary(max_size=5))
4292 _, _, _, default, optional, _decoded = values
4293 obj = self.base_klass(
4301 pprint(obj, big_blobs=True, with_decode_path=True)
4302 self.assertFalse(obj.expled)
4303 obj_encoded = obj.encode()
4304 self.assertEqual(encode2pass(obj), obj_encoded)
4305 self.additional_symmetric_check(value, obj_encoded)
4306 obj_expled = obj(value, expl=tag_expl)
4307 self.assertTrue(obj_expled.expled)
4309 list(obj_expled.pps())
4310 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4311 obj_expled_encoded = obj_expled.encode()
4312 ctx_copied = deepcopy(ctx_dummy)
4313 obj_decoded, tail = obj_expled.decode(
4314 obj_expled_encoded + tail_junk,
4318 self.assertDictEqual(ctx_copied, ctx_dummy)
4320 list(obj_decoded.pps())
4321 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4322 self.assertEqual(tail, tail_junk)
4323 self.assertEqual(obj_decoded, obj_expled)
4324 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4325 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4326 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4327 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4328 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4330 obj_decoded.expl_llen,
4331 len(len_encode(len(obj_encoded))),
4333 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4334 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4337 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4339 self.assertEqual(obj_decoded.expl_offset, offset)
4340 assert_exceeding_data(
4342 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4347 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4348 base_klass = GeneralizedTime
4350 min_datetime = datetime(1900, 1, 1)
4351 max_datetime = datetime(9999, 12, 31)
4352 evgen_mode_skip_value = False
4354 def additional_symmetric_check(self, value, obj_encoded):
4355 if value.microsecond > 0:
4356 self.assertFalse(obj_encoded.endswith(b"0Z"))
4358 def test_repr_not_ready(self):
4359 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4360 repr(GeneralizedTime())
4362 def test_x690_vector_valid(self):
4366 b"19920722132100.3Z",
4368 GeneralizedTime(data)
4370 def test_x690_vector_invalid(self):
4373 b"19920622123421.0Z",
4374 b"19920722132100.30Z",
4376 with self.assertRaises(DecodeError) as err:
4377 GeneralizedTime(data)
4380 def test_go_vectors_invalid(self):
4392 b"-20100102030410Z",
4393 b"2010-0102030410Z",
4394 b"2010-0002030410Z",
4395 b"201001-02030410Z",
4396 b"20100102-030410Z",
4397 b"2010010203-0410Z",
4398 b"201001020304-10Z",
4399 # These ones are INVALID in *DER*, but accepted
4400 # by Go's encoding/asn1
4401 b"20100102030405+0607",
4402 b"20100102030405-0607",
4404 with self.assertRaises(DecodeError) as err:
4405 GeneralizedTime(data)
4408 def test_go_vectors_valid(self):
4410 GeneralizedTime(b"20100102030405Z").todatetime(),
4411 datetime(2010, 1, 2, 3, 4, 5, 0),
4414 def test_go_vectors_valid_ber(self):
4416 b"20100102030405+0607",
4417 b"20100102030405-0607",
4419 GeneralizedTime(data, ctx={"bered": True})
4421 def test_utc_offsets(self):
4422 """Some know equal UTC offsets
4425 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4429 "200101011130-0700",
4430 "200101011500-03:30",
4433 self.assertEqual(dts[0], dts[1])
4434 self.assertEqual(dts[0], dts[2])
4435 self.assertEqual(dts[0], dts[3])
4437 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4438 @given(data_strategy())
4439 def test_valid_ber(self, d):
4440 min_year = 1901 if PY2 else 2
4441 year = d.draw(integers(min_value=min_year, max_value=9999))
4442 month = d.draw(integers(min_value=1, max_value=12))
4443 day = d.draw(integers(min_value=1, max_value=28))
4444 hours = d.draw(integers(min_value=0, max_value=23))
4445 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4446 dt = datetime(year, month, day, hours)
4447 fractions_sign = d.draw(sampled_from(" ,."))
4449 if fractions_sign != " ":
4450 fractions = random()
4451 if d.draw(booleans()):
4452 minutes = d.draw(integers(min_value=0, max_value=59))
4453 data += "%02d" % minutes
4454 dt += timedelta(seconds=60 * minutes)
4455 if d.draw(booleans()):
4456 seconds = d.draw(integers(min_value=0, max_value=59))
4457 data += "%02d" % seconds
4458 dt += timedelta(seconds=seconds)
4459 if fractions is not None:
4460 dt += timedelta(microseconds=10**6 * fractions)
4461 elif fractions is not None:
4462 dt += timedelta(seconds=60 * fractions)
4463 elif fractions is not None:
4464 dt += timedelta(seconds=3600 * fractions)
4465 if fractions is not None:
4466 data += fractions_sign + str(fractions)[2:]
4467 if d.draw(booleans()):
4469 elif d.draw(booleans()):
4470 offset_hour = d.draw(integers(min_value=0, max_value=13))
4472 if d.draw(booleans()):
4477 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4478 data += "%02d" % offset_hour
4479 minutes_separator = d.draw(sampled_from((None, "", ":")))
4480 if minutes_separator is not None:
4481 offset_minute = d.draw(integers(min_value=0, max_value=59))
4482 dt -= timedelta(seconds=sign * 60 * offset_minute)
4483 data += "%s%02d" % (minutes_separator, offset_minute)
4484 data = data.encode("ascii")
4485 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4487 GeneralizedTime().decod(data_der)
4492 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4495 mktime(obj.todatetime().timetuple()),
4496 mktime(dt.timetuple()),
4499 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4500 self.assertEqual(obj.ber_encoded, not dered)
4501 self.assertEqual(obj.bered, not dered)
4502 self.assertEqual(obj.ber_raw, None if dered else data)
4503 self.assertEqual(obj.encode() == data_der, dered)
4508 def test_invalid_ber(self):
4510 # "00010203040506.07",
4511 "-0010203040506.07",
4512 "0001-203040506.07",
4513 "000102-3040506.07",
4514 "00010203-40506.07",
4515 "0001020304-506.07",
4516 "000102030405-6.07",
4517 "00010203040506.-7",
4518 "+0010203040506.07",
4519 "0001+203040506.07",
4520 "000102+3040506.07",
4521 "00010203+40506.07",
4522 "0001020304+506.07",
4523 "000102030405+6.07",
4524 "00010203040506.+7",
4525 " 0010203040506.07",
4526 "0001 203040506.07",
4527 "000102 3040506.07",
4528 "00010203 40506.07",
4529 "0001020304 506.07",
4530 "000102030405 6.07",
4531 "00010203040506. 7",
4532 "001 0203040506.07",
4533 "00012 03040506.07",
4534 "0001023 040506.07",
4535 "000102034 0506.07",
4536 "00010203045 06.07",
4537 "0001020304056 .07",
4538 "00010203040506.7 ",
4618 "00010203040506.07+15",
4619 "00010203040506.07-15",
4620 "00010203040506.07+14:60",
4621 "00010203040506.07+1460",
4622 "00010203040506.07-1460",
4623 "00010203040506.07+00:60",
4624 "00010203040506.07-00:60",
4626 "00010203040506+15",
4627 "00010203040506-15",
4628 "00010203040506+14:60",
4629 "00010203040506+1460",
4630 "00010203040506-1460",
4631 "00010203040506+00:60",
4632 "00010203040506-00:60",
4641 with self.assertRaises(DecodeError):
4642 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4643 data = data.replace(".", ",")
4644 with self.assertRaises(DecodeError):
4645 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4649 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4650 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4652 binary(min_size=1, max_size=1),
4654 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4655 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4658 def test_junk(self, part0, part1, part2):
4659 junk = part0 + part1 + part2
4660 assume(not (set(junk) <= set(digits.encode("ascii"))))
4661 with self.assertRaises(DecodeError):
4662 GeneralizedTime().decode(
4663 GeneralizedTime.tag_default +
4664 len_encode(len(junk)) +
4670 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4671 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4673 binary(min_size=1, max_size=1),
4675 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4676 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4679 def test_junk_dm(self, part0, part1, part2):
4680 junk = part0 + part1 + part2
4681 assume(not (set(junk) <= set(digits.encode("ascii"))))
4682 with self.assertRaises(DecodeError):
4683 GeneralizedTime().decode(
4684 GeneralizedTime.tag_default +
4685 len_encode(len(junk)) +
4689 def test_ns_fractions(self):
4690 GeneralizedTime(b"20010101000000.000001Z")
4691 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4692 GeneralizedTime(b"20010101000000.0000001Z")
4694 def test_non_pure_integers(self):
4696 # b"20000102030405Z,
4703 b"20000102030405.+6Z",
4704 b"20000102030405.-6Z",
4711 b"20000102030405._6Z",
4712 b"20000102030405.6_Z",
4719 b"20000102030405. 6Z",
4726 b"20000102030405.6 Z",
4728 with self.assertRaises(DecodeError):
4729 GeneralizedTime(data)
4731 def test_aware(self):
4732 with assertRaisesRegex(self, ValueError, "only naive"):
4733 GeneralizedTime(datetime(2000, 1, 1, 1, tzinfo=UTC))
4736 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4737 base_klass = UTCTime
4739 min_datetime = datetime(2000, 1, 1)
4740 max_datetime = datetime(2049, 12, 31)
4741 evgen_mode_skip_value = False
4743 def additional_symmetric_check(self, value, obj_encoded):
4746 def test_repr_not_ready(self):
4747 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4750 def test_x690_vector_valid(self):
4758 def test_x690_vector_invalid(self):
4763 with self.assertRaises(DecodeError) as err:
4767 def test_go_vectors_invalid(self):
4793 # These ones are INVALID in *DER*, but accepted
4794 # by Go's encoding/asn1
4795 b"910506164540-0700",
4796 b"910506164540+0730",
4800 with self.assertRaises(DecodeError) as err:
4804 def test_go_vectors_valid(self):
4806 UTCTime(b"910506234540Z").todatetime(),
4807 datetime(1991, 5, 6, 23, 45, 40, 0),
4810 def test_non_pure_integers(self):
4839 with self.assertRaises(DecodeError):
4842 def test_x680_vector_valid_ber(self):
4844 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4845 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4846 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4847 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4849 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4850 obj = UTCTime().decod(data_der, ctx={"bered": True})
4851 self.assertEqual(obj, dt)
4852 self.assertEqual(obj.todatetime(), dt)
4853 self.assertTrue(obj.ber_encoded)
4854 self.assertTrue(obj.bered)
4855 self.assertEqual(obj.ber_raw, data)
4856 self.assertNotEqual(obj.encode(), data_der)
4859 def test_go_vectors_valid_ber(self):
4861 b"910506164540-0700",
4862 b"910506164540+0730",
4866 data = UTCTime.tag_default + len_encode(len(data)) + data
4867 obj = UTCTime().decod(data, ctx={"bered": True})
4868 self.assertTrue(obj.ber_encoded)
4869 self.assertTrue(obj.bered)
4870 self.assertNotEqual(obj.encode(), data)
4873 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4874 @given(data_strategy())
4875 def test_valid_ber(self, d):
4876 year = d.draw(integers(min_value=0, max_value=99))
4877 month = d.draw(integers(min_value=1, max_value=12))
4878 day = d.draw(integers(min_value=1, max_value=28))
4879 hours = d.draw(integers(min_value=0, max_value=23))
4880 minute = d.draw(integers(min_value=0, max_value=59))
4881 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4883 year + (2000 if year < 50 else 1900),
4890 if d.draw(booleans()):
4892 seconds = d.draw(integers(min_value=0, max_value=59))
4893 data += "%02d" % seconds
4894 dt += timedelta(seconds=seconds)
4895 if d.draw(booleans()):
4899 offset_hour = d.draw(integers(min_value=0, max_value=13))
4900 offset_minute = d.draw(integers(min_value=0, max_value=59))
4901 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4902 if d.draw(booleans()):
4908 data += "%02d%02d" % (offset_hour, offset_minute)
4909 data = data.encode("ascii")
4910 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4911 obj = UTCTime().decod(data_der, ctx={"bered": True})
4912 self.assertEqual(obj, dt)
4913 self.assertEqual(obj.todatetime(), dt)
4914 self.assertEqual(obj.ber_encoded, not dered)
4915 self.assertEqual(obj.bered, not dered)
4916 self.assertEqual(obj.ber_raw, None if dered else data)
4917 self.assertEqual(obj.encode() == data_der, dered)
4922 def test_invalid_ber(self):
4963 b"0001020304+0000Z",
4972 with self.assertRaises(DecodeError):
4973 UTCTime(data, ctx={"bered": True})
4974 data = data[:8] + data[8+2:]
4975 with self.assertRaises(DecodeError):
4976 UTCTime(data, ctx={"bered": True})
5021 b"000102030405+000",
5022 b"000102030405+000Z",
5023 b"000102030405+0000Z",
5024 b"000102030405+-101",
5025 b"000102030405+01-1",
5026 b"000102030405+0060",
5027 b"000102030405+1401",
5028 b"500101000002+0003",
5030 with self.assertRaises(DecodeError):
5031 UTCTime(data, ctx={"bered": True})
5033 @given(integers(min_value=0, max_value=49))
5034 def test_pre50(self, year):
5036 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5040 @given(integers(min_value=50, max_value=99))
5041 def test_post50(self, year):
5043 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5049 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5050 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5052 binary(min_size=1, max_size=1),
5054 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5055 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5058 def test_junk(self, part0, part1, part2):
5059 junk = part0 + part1 + part2
5060 assume(not (set(junk) <= set(digits.encode("ascii"))))
5061 with self.assertRaises(DecodeError):
5063 UTCTime.tag_default +
5064 len_encode(len(junk)) +
5068 def test_aware(self):
5069 with assertRaisesRegex(self, ValueError, "only naive"):
5070 UTCTime(datetime(2000, 1, 1, 1, tzinfo=UTC))
5074 def tlv_value_strategy(draw):
5075 tag_num = draw(integers(min_value=1))
5076 data = draw(binary())
5077 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5081 def any_values_strategy(draw, do_expl=False):
5082 value = draw(one_of(none(), tlv_value_strategy()))
5085 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5086 optional = draw(one_of(none(), booleans()))
5088 draw(integers(min_value=0)),
5089 draw(integers(min_value=0)),
5090 draw(integers(min_value=0)),
5092 return (value, expl, optional, _decoded)
5095 class AnyInherited(Any):
5099 class TestAny(CommonMixin, TestCase):
5102 def test_invalid_value_type(self):
5103 with self.assertRaises(InvalidValueType) as err:
5108 def test_optional(self, optional):
5109 obj = Any(optional=optional)
5110 self.assertEqual(obj.optional, optional)
5112 @given(tlv_value_strategy())
5113 def test_ready(self, value):
5115 self.assertFalse(obj.ready)
5118 pprint(obj, big_blobs=True, with_decode_path=True)
5119 with self.assertRaises(ObjNotReady) as err:
5122 with self.assertRaises(ObjNotReady) as err:
5125 self.assertTrue(obj.ready)
5128 pprint(obj, big_blobs=True, with_decode_path=True)
5131 def test_basic(self, value):
5132 integer_encoded = Integer(value).encode()
5134 Any(integer_encoded),
5135 Any(Integer(value)),
5136 Any(Any(Integer(value))),
5138 self.assertSequenceEqual(bytes(obj), integer_encoded)
5140 obj.decode(obj.encode())[0].vlen,
5141 len(integer_encoded),
5145 pprint(obj, big_blobs=True, with_decode_path=True)
5146 self.assertSequenceEqual(obj.encode(), integer_encoded)
5148 @given(tlv_value_strategy(), tlv_value_strategy())
5149 def test_comparison(self, value1, value2):
5150 for klass in (Any, AnyInherited):
5151 obj1 = klass(value1)
5152 obj2 = klass(value2)
5153 self.assertEqual(obj1 == obj2, value1 == value2)
5154 self.assertEqual(obj1 != obj2, value1 != value2)
5155 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5157 @given(data_strategy())
5158 def test_call(self, d):
5159 for klass in (Any, AnyInherited):
5165 ) = d.draw(any_values_strategy())
5166 obj_initial = klass(
5169 optional_initial or False,
5177 ) = d.draw(any_values_strategy(do_expl=True))
5178 obj = obj_initial(value, expl, optional)
5180 value_expected = None if value is None else value
5181 self.assertEqual(obj, value_expected)
5182 self.assertEqual(obj.expl_tag, expl or expl_initial)
5183 if obj.default is None:
5184 optional = optional_initial if optional is None else optional
5185 optional = False if optional is None else optional
5186 self.assertEqual(obj.optional, optional)
5188 def test_simultaneous_impl_expl(self):
5189 # override it, as Any does not have implicit tag
5192 def test_decoded(self):
5193 # override it, as Any does not have implicit tag
5196 @given(any_values_strategy())
5197 def test_copy(self, values):
5198 for klass in (Any, AnyInherited):
5199 obj = klass(*values)
5200 for copy_func in copy_funcs:
5201 obj_copied = copy_func(obj)
5202 self.assert_copied_basic_fields(obj, obj_copied)
5203 self.assertEqual(obj._value, obj_copied._value)
5205 @given(binary().map(OctetString))
5206 def test_stripped(self, value):
5208 with self.assertRaises(NotEnoughData):
5209 obj.decode(obj.encode()[:-1])
5212 tlv_value_strategy(),
5213 integers(min_value=1).map(tag_ctxc),
5215 def test_stripped_expl(self, value, tag_expl):
5216 obj = Any(value, expl=tag_expl)
5217 with self.assertRaises(NotEnoughData):
5218 obj.decode(obj.encode()[:-1])
5221 integers(min_value=31),
5222 integers(min_value=0),
5225 def test_bad_tag(self, tag, offset, decode_path):
5226 with self.assertRaises(DecodeError) as err:
5228 tag_encode(tag)[:-1],
5230 decode_path=decode_path,
5233 self.assertEqual(err.exception.offset, offset)
5234 self.assertEqual(err.exception.decode_path, decode_path)
5237 integers(min_value=128),
5238 integers(min_value=0),
5241 def test_bad_len(self, l, offset, decode_path):
5242 with self.assertRaises(DecodeError) as err:
5244 Any.tag_default + len_encode(l)[:-1],
5246 decode_path=decode_path,
5249 self.assertEqual(err.exception.offset, offset)
5250 self.assertEqual(err.exception.decode_path, decode_path)
5252 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5254 any_values_strategy(),
5255 integers().map(lambda x: Integer(x).encode()),
5256 integers(min_value=1).map(tag_ctxc),
5257 integers(min_value=0),
5261 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5262 for klass in (Any, AnyInherited):
5263 _, _, optional, _decoded = values
5264 obj = klass(value=value, optional=optional, _decoded=_decoded)
5267 pprint(obj, big_blobs=True, with_decode_path=True)
5268 self.assertFalse(obj.expled)
5269 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5270 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5271 obj_encoded = obj.encode()
5272 self.assertEqual(encode2pass(obj), obj_encoded)
5273 obj_expled = obj(value, expl=tag_expl)
5274 self.assertTrue(obj_expled.expled)
5275 tag_class, _, tag_num = tag_decode(tag_expl)
5276 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5278 list(obj_expled.pps())
5279 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5280 obj_expled_encoded = obj_expled.encode()
5281 ctx_copied = deepcopy(ctx_dummy)
5282 obj_decoded, tail = obj_expled.decode(
5283 obj_expled_encoded + tail_junk,
5287 self.assertDictEqual(ctx_copied, ctx_dummy)
5289 list(obj_decoded.pps())
5290 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5291 self.assertEqual(tail, tail_junk)
5292 self.assertEqual(obj_decoded, obj_expled)
5293 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5294 self.assertEqual(bytes(obj_decoded), bytes(obj))
5295 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5296 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5297 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5299 obj_decoded.expl_llen,
5300 len(len_encode(len(obj_encoded))),
5302 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5303 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5306 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5308 self.assertEqual(obj_decoded.expl_offset, offset)
5309 self.assertEqual(obj_decoded.tlen, 0)
5310 self.assertEqual(obj_decoded.llen, 0)
5311 self.assertEqual(obj_decoded.vlen, len(value))
5312 assert_exceeding_data(
5314 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5318 evgens = list(obj_expled.decode_evgen(
5319 obj_expled_encoded + tail_junk,
5321 decode_path=decode_path,
5324 self.assertEqual(len(evgens), 1)
5325 _decode_path, obj, tail = evgens[0]
5326 self.assertSequenceEqual(tail, tail_junk)
5327 self.assertEqual(_decode_path, decode_path)
5328 self.assertEqual(obj.expl_offset, offset)
5333 integers(min_value=1).map(tag_ctxc),
5334 integers(min_value=0, max_value=3),
5335 integers(min_value=0),
5339 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5340 chunk = Boolean(False, expl=expl).encode()
5342 OctetString.tag_default +
5344 b"".join([chunk] * chunks) +
5347 with self.assertRaises(LenIndefForm):
5351 decode_path=decode_path,
5353 obj, tail = Any().decode(
5356 decode_path=decode_path,
5357 ctx={"bered": True},
5359 self.assertSequenceEqual(tail, junk)
5360 self.assertEqual(obj.offset, offset)
5361 self.assertEqual(obj.tlvlen, len(encoded))
5362 self.assertTrue(obj.lenindef)
5363 self.assertFalse(obj.ber_encoded)
5364 self.assertTrue(obj.bered)
5366 self.assertTrue(obj.lenindef)
5367 self.assertFalse(obj.ber_encoded)
5368 self.assertTrue(obj.bered)
5371 pprint(obj, big_blobs=True, with_decode_path=True)
5372 with self.assertRaises(NotEnoughData) as err:
5376 decode_path=decode_path,
5377 ctx={"bered": True},
5379 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5380 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5382 class SeqOf(SequenceOf):
5383 schema = Boolean(expl=expl)
5385 class Seq(Sequence):
5387 ("type", ObjectIdentifier(defines=((("value",), {
5388 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5393 ("type", ObjectIdentifier("1.2.3")),
5394 ("value", Any(encoded)),
5396 seq_encoded = seq.encode()
5397 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5398 self.assertIsNotNone(seq_decoded["value"].defined)
5400 list(seq_decoded.pps())
5401 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5402 self.assertTrue(seq_decoded.bered)
5403 self.assertFalse(seq_decoded["type"].bered)
5404 self.assertTrue(seq_decoded["value"].bered)
5406 chunk = chunk[:-1] + b"\x01"
5407 chunks = b"".join([chunk] * (chunks + 1))
5408 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5410 ("type", ObjectIdentifier("1.2.3")),
5411 ("value", Any(encoded)),
5413 seq_encoded = seq.encode()
5414 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5415 self.assertIsNotNone(seq_decoded["value"].defined)
5417 list(seq_decoded.pps())
5418 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5419 self.assertTrue(seq_decoded.bered)
5420 self.assertFalse(seq_decoded["type"].bered)
5421 self.assertTrue(seq_decoded["value"].bered)
5425 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5427 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5428 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5430 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5431 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5433 min_size=len(names),
5434 max_size=len(names),
5437 (name, Integer(**tag_kwargs))
5438 for name, tag_kwargs in zip(names, tags)
5441 if value_required or draw(booleans()):
5442 value = draw(tuples(
5443 sampled_from([name for name, _ in schema]),
5444 integers().map(Integer),
5448 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5449 default = draw(one_of(
5451 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5453 optional = draw(one_of(none(), booleans()))
5455 draw(integers(min_value=0)),
5456 draw(integers(min_value=0)),
5457 draw(integers(min_value=0)),
5459 return (schema, value, expl, default, optional, _decoded)
5462 class ChoiceInherited(Choice):
5466 class TestChoice(CommonMixin, TestCase):
5468 schema = (("whatever", Boolean()),)
5471 def test_schema_required(self):
5472 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5475 def test_impl_forbidden(self):
5476 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5477 Choice(impl=b"whatever")
5479 def test_invalid_value_type(self):
5480 with self.assertRaises(InvalidValueType) as err:
5481 self.base_klass(123)
5483 with self.assertRaises(ObjUnknown) as err:
5484 self.base_klass(("whenever", Boolean(False)))
5486 with self.assertRaises(InvalidValueType) as err:
5487 self.base_klass(("whatever", Integer(123)))
5491 def test_optional(self, optional):
5492 obj = self.base_klass(
5493 default=self.base_klass(("whatever", Boolean(False))),
5496 self.assertTrue(obj.optional)
5499 def test_ready(self, value):
5500 obj = self.base_klass()
5501 self.assertFalse(obj.ready)
5504 pprint(obj, big_blobs=True, with_decode_path=True)
5505 self.assertIsNone(obj["whatever"])
5506 with self.assertRaises(ObjNotReady) as err:
5509 with self.assertRaises(ObjNotReady) as err:
5511 obj["whatever"] = Boolean()
5512 self.assertFalse(obj.ready)
5515 pprint(obj, big_blobs=True, with_decode_path=True)
5516 obj["whatever"] = Boolean(value)
5517 self.assertTrue(obj.ready)
5520 pprint(obj, big_blobs=True, with_decode_path=True)
5522 @given(booleans(), booleans())
5523 def test_comparison(self, value1, value2):
5524 class WahlInherited(self.base_klass):
5526 for klass in (self.base_klass, WahlInherited):
5527 obj1 = klass(("whatever", Boolean(value1)))
5528 obj2 = klass(("whatever", Boolean(value2)))
5529 self.assertEqual(obj1 == obj2, value1 == value2)
5530 self.assertEqual(obj1 != obj2, value1 != value2)
5531 self.assertEqual(obj1 == obj2._value, value1 == value2)
5532 self.assertFalse(obj1 == obj2._value[1])
5534 @given(data_strategy())
5535 def test_call(self, d):
5536 for klass in (Choice, ChoiceInherited):
5544 ) = d.draw(choice_values_strategy())
5547 schema = schema_initial
5549 value=value_initial,
5551 default=default_initial,
5552 optional=optional_initial or False,
5553 _decoded=_decoded_initial,
5562 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5563 obj = obj_initial(value, expl, default, optional)
5565 value_expected = default if value is None else value
5567 default_initial if value_expected is None
5570 self.assertEqual(obj.choice, value_expected[0])
5571 self.assertEqual(obj.value, int(value_expected[1]))
5572 self.assertEqual(obj.expl_tag, expl or expl_initial)
5573 default_expect = default_initial if default is None else default
5574 if default_expect is not None:
5575 self.assertEqual(obj.default.choice, default_expect[0])
5576 self.assertEqual(obj.default.value, int(default_expect[1]))
5577 if obj.default is None:
5578 optional = optional_initial if optional is None else optional
5579 optional = False if optional is None else optional
5582 self.assertEqual(obj.optional, optional)
5583 self.assertEqual(obj.specs, obj_initial.specs)
5585 def test_simultaneous_impl_expl(self):
5586 # override it, as Any does not have implicit tag
5589 def test_decoded(self):
5590 # override it, as Any does not have implicit tag
5593 @given(choice_values_strategy())
5594 def test_copy(self, values):
5595 _schema, value, expl, default, optional, _decoded = values
5597 class Wahl(self.base_klass):
5599 register_class(Wahl)
5604 optional=optional or False,
5607 for copy_func in copy_funcs:
5608 obj_copied = copy_func(obj)
5609 self.assertIsNone(obj.tag)
5610 self.assertIsNone(obj_copied.tag)
5611 # hack for assert_copied_basic_fields
5612 obj.tag = "whatever"
5613 obj_copied.tag = "whatever"
5614 self.assert_copied_basic_fields(obj, obj_copied)
5616 self.assertEqual(obj._value, obj_copied._value)
5617 self.assertEqual(obj.specs, obj_copied.specs)
5620 def test_stripped(self, value):
5621 obj = self.base_klass(("whatever", Boolean(value)))
5622 with self.assertRaises(NotEnoughData):
5623 obj.decode(obj.encode()[:-1])
5627 integers(min_value=1).map(tag_ctxc),
5629 def test_stripped_expl(self, value, tag_expl):
5630 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5631 with self.assertRaises(NotEnoughData):
5632 obj.decode(obj.encode()[:-1])
5634 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5635 @given(data_strategy())
5636 def test_symmetric(self, d):
5637 _schema, value, _, default, optional, _decoded = d.draw(
5638 choice_values_strategy(value_required=True)
5640 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5641 offset = d.draw(integers(min_value=0))
5642 tail_junk = d.draw(binary(max_size=5))
5643 decode_path = d.draw(decode_path_strat)
5645 class Wahl(self.base_klass):
5655 pprint(obj, big_blobs=True, with_decode_path=True)
5656 self.assertFalse(obj.expled)
5657 self.assertEqual(obj.tag_order, obj.value.tag_order)
5658 obj_encoded = obj.encode()
5659 self.assertEqual(encode2pass(obj), obj_encoded)
5660 obj_expled = obj(value, expl=tag_expl)
5661 self.assertTrue(obj_expled.expled)
5662 tag_class, _, tag_num = tag_decode(tag_expl)
5663 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5665 list(obj_expled.pps())
5666 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5667 obj_expled_encoded = obj_expled.encode()
5668 ctx_copied = deepcopy(ctx_dummy)
5669 obj_decoded, tail = obj_expled.decode(
5670 obj_expled_encoded + tail_junk,
5674 self.assertDictEqual(ctx_copied, ctx_dummy)
5676 list(obj_decoded.pps())
5677 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5678 self.assertEqual(tail, tail_junk)
5679 self.assertEqual(obj_decoded, obj_expled)
5680 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5681 self.assertEqual(obj_decoded.value, obj_expled.value)
5682 self.assertEqual(obj_decoded.choice, obj.choice)
5683 self.assertEqual(obj_decoded.value, obj.value)
5684 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5685 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5686 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5688 obj_decoded.expl_llen,
5689 len(len_encode(len(obj_encoded))),
5691 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5692 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5695 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5697 self.assertEqual(obj_decoded.expl_offset, offset)
5698 self.assertSequenceEqual(
5700 obj_decoded.value.fulloffset - offset:
5701 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5705 assert_exceeding_data(
5707 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5711 evgens = list(obj_expled.decode_evgen(
5712 obj_expled_encoded + tail_junk,
5714 decode_path=decode_path,
5717 self.assertEqual(len(evgens), 2)
5718 _decode_path, obj, tail = evgens[0]
5719 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5720 _decode_path, obj, tail = evgens[1]
5721 self.assertSequenceEqual(tail, tail_junk)
5722 self.assertEqual(_decode_path, decode_path)
5723 self.assertEqual(obj.expl_offset, offset)
5728 def test_set_get(self, value):
5731 ("erste", Boolean()),
5732 ("zweite", Integer()),
5735 with self.assertRaises(ObjUnknown) as err:
5736 obj["whatever"] = "whenever"
5737 with self.assertRaises(InvalidValueType) as err:
5738 obj["zweite"] = Boolean(False)
5739 obj["zweite"] = Integer(value)
5741 with self.assertRaises(ObjUnknown) as err:
5744 self.assertIsNone(obj["erste"])
5745 self.assertEqual(obj["zweite"], Integer(value))
5747 def test_tag_mismatch(self):
5750 ("erste", Boolean()),
5752 int_encoded = Integer(123).encode()
5753 bool_encoded = Boolean(False).encode()
5755 obj.decode(bool_encoded)
5756 with self.assertRaises(TagMismatch):
5757 obj.decode(int_encoded)
5759 def test_tag_mismatch_underlying(self):
5760 class SeqOfBoolean(SequenceOf):
5763 class SeqOfInteger(SequenceOf):
5768 ("erste", SeqOfBoolean()),
5771 int_encoded = SeqOfInteger((Integer(123),)).encode()
5772 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5774 obj.decode(bool_encoded)
5775 with self.assertRaises(TagMismatch) as err:
5776 obj.decode(int_encoded)
5777 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5781 def seq_values_strategy(draw, seq_klass, do_expl=False):
5783 if draw(booleans()):
5785 value._value = draw(dictionaries(
5788 booleans().map(Boolean),
5789 integers().map(Integer),
5793 if draw(booleans()):
5794 schema = list(draw(dictionaries(
5797 booleans().map(Boolean),
5798 integers().map(Integer),
5804 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5806 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5808 if draw(booleans()):
5809 default = seq_klass()
5810 default._value = draw(dictionaries(
5813 booleans().map(Boolean),
5814 integers().map(Integer),
5817 optional = draw(one_of(none(), booleans()))
5819 draw(integers(min_value=0)),
5820 draw(integers(min_value=0)),
5821 draw(integers(min_value=0)),
5823 return (value, schema, impl, expl, default, optional, _decoded)
5827 def sequence_strategy(draw, seq_klass):
5828 inputs = draw(lists(
5830 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5831 tuples(just(Integer), integers(), one_of(none(), integers())),
5836 integers(min_value=1),
5837 min_size=len(inputs),
5838 max_size=len(inputs),
5841 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5842 for tag, expled in zip(tags, draw(lists(
5844 min_size=len(inputs),
5845 max_size=len(inputs),
5849 for i, optional in enumerate(draw(lists(
5850 sampled_from(("required", "optional", "empty")),
5851 min_size=len(inputs),
5852 max_size=len(inputs),
5854 if optional in ("optional", "empty"):
5855 inits[i]["optional"] = True
5856 if optional == "empty":
5858 empties = set(empties)
5859 names = list(draw(sets(
5861 min_size=len(inputs),
5862 max_size=len(inputs),
5865 for i, (klass, value, default) in enumerate(inputs):
5866 schema.append((names[i], klass(default=default, **inits[i])))
5867 seq_name = draw(text_letters())
5868 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5871 for i, (klass, value, default) in enumerate(inputs):
5878 "default_value": None if spec.default is None else default,
5882 expect["optional"] = True
5884 expect["presented"] = True
5885 expect["value"] = value
5887 expect["optional"] = True
5888 if default is not None and default == value:
5889 expect["presented"] = False
5890 seq[name] = klass(value)
5891 expects.append(expect)
5896 def sequences_strategy(draw, seq_klass):
5897 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5899 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5900 for tag, expled in zip(tags, draw(lists(
5907 i for i, is_default in enumerate(draw(lists(
5913 names = list(draw(sets(
5918 seq_expectses = draw(lists(
5919 sequence_strategy(seq_klass=seq_klass),
5923 seqs = [seq for seq, _ in seq_expectses]
5925 for i, (name, seq) in enumerate(zip(names, seqs)):
5928 seq(default=(seq if i in defaulted else None), **inits[i]),
5930 seq_name = draw(text_letters())
5931 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5934 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5937 "expects": expects_inner,
5940 seq_outer[name] = seq_inner
5941 if seq_outer.specs[name].default is None:
5942 expect["presented"] = True
5943 expect_outers.append(expect)
5944 return seq_outer, expect_outers
5947 class SeqMixing(object):
5948 def test_invalid_value_type(self):
5949 with self.assertRaises(InvalidValueType) as err:
5950 self.base_klass(123)
5953 def test_invalid_value_type_set(self):
5954 class Seq(self.base_klass):
5955 schema = (("whatever", Boolean()),)
5957 with self.assertRaises(InvalidValueType) as err:
5958 seq["whatever"] = Integer(123)
5962 def test_optional(self, optional):
5963 obj = self.base_klass(default=self.base_klass(), optional=optional)
5964 self.assertTrue(obj.optional)
5966 @given(data_strategy())
5967 def test_ready(self, d):
5969 str(i): v for i, v in enumerate(d.draw(lists(
5976 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5983 for name in d.draw(permutations(
5984 list(ready.keys()) + list(non_ready.keys()),
5986 schema_input.append((name, Boolean()))
5988 class Seq(self.base_klass):
5989 schema = tuple(schema_input)
5991 for name in ready.keys():
5993 seq[name] = Boolean()
5994 self.assertFalse(seq.ready)
5997 pprint(seq, big_blobs=True, with_decode_path=True)
5998 for name, value in ready.items():
5999 seq[name] = Boolean(value)
6000 self.assertFalse(seq.ready)
6003 pprint(seq, big_blobs=True, with_decode_path=True)
6004 with self.assertRaises(ObjNotReady) as err:
6007 with self.assertRaises(ObjNotReady) as err:
6009 for name, value in non_ready.items():
6010 seq[name] = Boolean(value)
6011 self.assertTrue(seq.ready)
6014 pprint(seq, big_blobs=True, with_decode_path=True)
6016 @given(data_strategy())
6017 def test_call(self, d):
6018 class SeqInherited(self.base_klass):
6020 for klass in (self.base_klass, SeqInherited):
6029 ) = d.draw(seq_values_strategy(seq_klass=klass))
6030 obj_initial = klass(
6036 optional_initial or False,
6047 ) = d.draw(seq_values_strategy(
6049 do_expl=impl_initial is None,
6051 obj = obj_initial(value, impl, expl, default, optional)
6052 value_expected = default if value is None else value
6054 default_initial if value_expected is None
6057 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
6058 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6059 self.assertEqual(obj.expl_tag, expl or expl_initial)
6061 {} if obj.default is None else obj.default._value,
6062 getattr(default_initial if default is None else default, "_value", {}),
6064 if obj.default is None:
6065 optional = optional_initial if optional is None else optional
6066 optional = False if optional is None else optional
6069 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6070 self.assertEqual(obj.optional, optional)
6072 @given(data_strategy())
6073 def test_copy(self, d):
6074 class SeqInherited(self.base_klass):
6076 register_class(SeqInherited)
6077 for klass in (self.base_klass, SeqInherited):
6078 values = d.draw(seq_values_strategy(seq_klass=klass))
6079 obj = klass(*values)
6080 for copy_func in copy_funcs:
6081 obj_copied = copy_func(obj)
6082 self.assert_copied_basic_fields(obj, obj_copied)
6083 self.assertEqual(obj.specs, obj_copied.specs)
6084 self.assertEqual(obj._value, obj_copied._value)
6086 @given(data_strategy())
6087 def test_stripped(self, d):
6088 value = d.draw(integers())
6089 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6091 class Seq(self.base_klass):
6093 schema = (("whatever", Integer()),)
6095 seq["whatever"] = Integer(value)
6096 with self.assertRaises(NotEnoughData):
6097 seq.decode(seq.encode()[:-1])
6099 @given(data_strategy())
6100 def test_stripped_expl(self, d):
6101 value = d.draw(integers())
6102 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6104 class Seq(self.base_klass):
6106 schema = (("whatever", Integer()),)
6108 seq["whatever"] = Integer(value)
6109 with self.assertRaises(NotEnoughData):
6110 seq.decode(seq.encode()[:-1])
6112 @given(integers(min_value=3), binary(min_size=2))
6113 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6114 junk = tag_encode(junk_tag_num) + junk
6116 _, _, len_encoded = tag_strip(memoryview(junk))
6117 len_decode(len_encoded)
6123 class Seq(self.base_klass):
6125 ("whatever", Integer()),
6127 ("whenever", Integer()),
6130 seq["whatever"] = Integer(123)
6131 seq["junk"] = Any(junk)
6132 seq["whenever"] = Integer(123)
6133 with self.assertRaises(DecodeError):
6134 seq.decode(seq.encode())
6137 integers(min_value=31),
6138 integers(min_value=0),
6141 def test_bad_tag(self, tag, offset, decode_path):
6142 with self.assertRaises(DecodeError) as err:
6143 self.base_klass().decode(
6144 tag_encode(tag)[:-1],
6146 decode_path=decode_path,
6149 self.assertEqual(err.exception.offset, offset)
6150 self.assertEqual(err.exception.decode_path, decode_path)
6153 integers(min_value=128),
6154 integers(min_value=0),
6157 def test_bad_len(self, l, offset, decode_path):
6158 with self.assertRaises(DecodeError) as err:
6159 self.base_klass().decode(
6160 self.base_klass.tag_default + len_encode(l)[:-1],
6162 decode_path=decode_path,
6165 self.assertEqual(err.exception.offset, offset)
6166 self.assertEqual(err.exception.decode_path, decode_path)
6168 def _assert_expects(self, seq, expects):
6169 for expect in expects:
6171 seq.specs[expect["name"]].optional,
6174 if expect["default_value"] is not None:
6176 seq.specs[expect["name"]].default,
6177 expect["default_value"],
6179 if expect["presented"]:
6180 self.assertIn(expect["name"], seq)
6181 self.assertEqual(seq[expect["name"]], expect["value"])
6183 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6184 @given(data_strategy())
6185 def test_symmetric(self, d):
6186 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6187 tail_junk = d.draw(binary(max_size=5))
6188 decode_path = d.draw(decode_path_strat)
6189 self.assertTrue(seq.ready)
6190 self.assertFalse(seq.decoded)
6191 self._assert_expects(seq, expects)
6194 pprint(seq, big_blobs=True, with_decode_path=True)
6195 self.assertTrue(seq.ready)
6196 seq_encoded = seq.encode()
6197 self.assertEqual(encode2pass(seq), seq_encoded)
6198 seq_encoded_cer = encode_cer(seq)
6199 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6200 self.assertSequenceEqual(
6201 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6204 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6205 self.assertFalse(seq_decoded.lenindef)
6206 self.assertFalse(seq_decoded.ber_encoded)
6207 self.assertFalse(seq_decoded.bered)
6209 t, _, lv = tag_strip(seq_encoded)
6210 _, _, v = len_decode(lv)
6211 seq_encoded_lenindef = t + LENINDEF + v + EOC
6212 with self.assertRaises(DecodeError):
6213 seq.decode(seq_encoded_lenindef)
6214 ctx_copied = deepcopy(ctx_dummy)
6215 ctx_copied["bered"] = True
6216 seq_decoded_lenindef, tail_lenindef = seq.decode(
6217 seq_encoded_lenindef + tail_junk,
6220 del ctx_copied["bered"]
6221 self.assertDictEqual(ctx_copied, ctx_dummy)
6222 self.assertTrue(seq_decoded_lenindef.lenindef)
6223 self.assertTrue(seq_decoded_lenindef.bered)
6224 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6225 self.assertTrue(seq_decoded_lenindef.lenindef)
6226 self.assertTrue(seq_decoded_lenindef.bered)
6227 with self.assertRaises(DecodeError):
6228 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6229 with self.assertRaises(DecodeError):
6230 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6231 repr(seq_decoded_lenindef)
6232 list(seq_decoded_lenindef.pps())
6233 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6234 self.assertTrue(seq_decoded_lenindef.ready)
6236 for decoded, decoded_tail, encoded in (
6237 (seq_decoded, tail, seq_encoded),
6238 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6240 self.assertEqual(decoded_tail, tail_junk)
6241 self._assert_expects(decoded, expects)
6242 self.assertEqual(seq, decoded)
6243 self.assertEqual(decoded.encode(), seq_encoded)
6244 self.assertEqual(decoded.tlvlen, len(encoded))
6245 for expect in expects:
6246 if not expect["presented"]:
6247 self.assertNotIn(expect["name"], decoded)
6249 self.assertIn(expect["name"], decoded)
6250 obj = decoded[expect["name"]]
6251 self.assertTrue(obj.decoded)
6252 offset = obj.expl_offset if obj.expled else obj.offset
6253 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6254 self.assertSequenceEqual(
6255 seq_encoded[offset:offset + tlvlen],
6259 evgens = list(seq.decode_evgen(
6260 encoded + decoded_tail,
6261 decode_path=decode_path,
6262 ctx={"bered": True},
6264 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6265 for _decode_path, obj, _ in evgens[:-1]:
6266 self.assertEqual(_decode_path[:-1], decode_path)
6269 _decode_path, obj, tail = evgens[-1]
6270 self.assertEqual(_decode_path, decode_path)
6274 assert_exceeding_data(
6276 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6280 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6281 @given(data_strategy())
6282 def test_symmetric_with_seq(self, d):
6283 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6284 self.assertTrue(seq.ready)
6285 seq_encoded = seq.encode()
6286 self.assertEqual(encode2pass(seq), seq_encoded)
6287 seq_decoded, tail = seq.decode(seq_encoded)
6288 self.assertEqual(tail, b"")
6289 self.assertTrue(seq.ready)
6290 self.assertEqual(seq, seq_decoded)
6291 self.assertEqual(seq_decoded.encode(), seq_encoded)
6292 for expect_outer in expect_outers:
6293 if not expect_outer["presented"]:
6294 self.assertNotIn(expect_outer["name"], seq_decoded)
6296 self.assertIn(expect_outer["name"], seq_decoded)
6297 obj = seq_decoded[expect_outer["name"]]
6298 self.assertTrue(obj.decoded)
6299 offset = obj.expl_offset if obj.expled else obj.offset
6300 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6301 self.assertSequenceEqual(
6302 seq_encoded[offset:offset + tlvlen],
6305 self._assert_expects(obj, expect_outer["expects"])
6307 @given(data_strategy())
6308 def test_default_disappears(self, d):
6309 _schema = list(d.draw(dictionaries(
6311 sets(integers(), min_size=2, max_size=2),
6315 class Seq(self.base_klass):
6317 (n, Integer(default=d))
6318 for n, (_, d) in _schema
6321 for name, (value, _) in _schema:
6322 seq[name] = Integer(value)
6323 self.assertEqual(len(seq._value), len(_schema))
6324 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6325 self.assertGreater(len(seq.encode()), len(empty_seq))
6326 for name, (_, default) in _schema:
6327 seq[name] = Integer(default)
6328 self.assertEqual(len(seq._value), 0)
6329 self.assertSequenceEqual(seq.encode(), empty_seq)
6331 @given(data_strategy())
6332 def test_encoded_default_not_accepted(self, d):
6333 _schema = list(d.draw(dictionaries(
6338 tags = [tag_encode(tag) for tag in d.draw(sets(
6339 integers(min_value=1),
6340 min_size=len(_schema),
6341 max_size=len(_schema),
6345 schema = (("int", Integer()),)
6347 class SeqWithoutDefault(self.base_klass):
6350 for (n, _), t in zip(_schema, tags)
6352 seq_without_default = SeqWithoutDefault()
6353 for name, value in _schema:
6354 seq_without_default[name] = Wahl(("int", Integer(value)))
6355 seq_encoded = seq_without_default.encode()
6356 seq_without_default.decode(seq_encoded)
6358 len(list(seq_without_default.decode_evgen(seq_encoded))),
6359 len(_schema) * 2 + 1,
6362 class SeqWithDefault(self.base_klass):
6364 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6365 for (n, v), t in zip(_schema, tags)
6367 seq_with_default = SeqWithDefault()
6368 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6369 seq_with_default.decode(seq_encoded)
6370 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6371 list(seq_with_default.decode_evgen(seq_encoded))
6372 for ctx in ({"bered": True}, {"allow_default_values": True}):
6373 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6374 self.assertTrue(seq_decoded.ber_encoded)
6375 self.assertTrue(seq_decoded.bered)
6376 seq_decoded = copy(seq_decoded)
6377 self.assertTrue(seq_decoded.ber_encoded)
6378 self.assertTrue(seq_decoded.bered)
6379 for name, value in _schema:
6380 self.assertEqual(seq_decoded[name], seq_with_default[name])
6381 self.assertEqual(seq_decoded[name].value, value)
6383 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6387 seq_without_default = SeqWithoutDefault()
6388 for name, value in _schema:
6389 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6390 seq_encoded = seq_without_default.encode()
6391 seq_with_default.decode(seq_encoded)
6393 len(list(seq_with_default.decode_evgen(seq_encoded))),
6397 @given(data_strategy())
6398 def test_missing_from_spec(self, d):
6399 names = list(d.draw(sets(text_letters(), min_size=2)))
6400 tags = [tag_encode(tag) for tag in d.draw(sets(
6401 integers(min_value=1),
6402 min_size=len(names),
6403 max_size=len(names),
6405 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6407 class SeqFull(self.base_klass):
6408 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6409 seq_full = SeqFull()
6410 for i, name in enumerate(names):
6411 seq_full[name] = Integer(i)
6412 seq_encoded = seq_full.encode()
6413 altered = names_tags[:-2] + names_tags[-1:]
6415 class SeqMissing(self.base_klass):
6416 schema = [(n, Integer(impl=t)) for n, t in altered]
6417 seq_missing = SeqMissing()
6418 with self.assertRaises(TagMismatch):
6419 seq_missing.decode(seq_encoded)
6420 with self.assertRaises(TagMismatch):
6421 list(seq_missing.decode_evgen(seq_encoded))
6423 def test_bered(self):
6424 class Seq(self.base_klass):
6425 schema = (("underlying", Boolean()),)
6426 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6427 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6428 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6429 self.assertFalse(decoded.ber_encoded)
6430 self.assertFalse(decoded.lenindef)
6431 self.assertTrue(decoded.bered)
6432 decoded = copy(decoded)
6433 self.assertFalse(decoded.ber_encoded)
6434 self.assertFalse(decoded.lenindef)
6435 self.assertTrue(decoded.bered)
6437 class Seq(self.base_klass):
6438 schema = (("underlying", OctetString()),)
6440 tag_encode(form=TagFormConstructed, num=4) +
6442 OctetString(b"whatever").encode() +
6445 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6446 with self.assertRaises(DecodeError):
6447 Seq().decode(encoded)
6448 with self.assertRaises(DecodeError):
6449 list(Seq().decode_evgen(encoded))
6450 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6451 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6452 self.assertFalse(decoded.ber_encoded)
6453 self.assertFalse(decoded.lenindef)
6454 self.assertTrue(decoded.bered)
6455 decoded = copy(decoded)
6456 self.assertFalse(decoded.ber_encoded)
6457 self.assertFalse(decoded.lenindef)
6458 self.assertTrue(decoded.bered)
6461 class TestSequence(SeqMixing, CommonMixin, TestCase):
6462 base_klass = Sequence
6468 def test_remaining(self, value, junk):
6469 class Seq(Sequence):
6471 ("whatever", Integer()),
6473 int_encoded = Integer(value).encode()
6475 Sequence.tag_default,
6476 len_encode(len(int_encoded + junk)),
6479 with assertRaisesRegex(self, DecodeError, "remaining"):
6480 Seq().decode(junked)
6482 @given(sets(text_letters(), min_size=2))
6483 def test_obj_unknown(self, names):
6484 missing = names.pop()
6486 class Seq(Sequence):
6487 schema = [(n, Boolean()) for n in names]
6489 with self.assertRaises(ObjUnknown) as err:
6492 with self.assertRaises(ObjUnknown) as err:
6493 seq[missing] = Boolean()
6496 def test_x690_vector(self):
6497 class Seq(Sequence):
6499 ("name", IA5String()),
6502 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6503 self.assertEqual(seq["name"], "Smith")
6504 self.assertEqual(seq["ok"], True)
6507 class TestSet(SeqMixing, CommonMixin, TestCase):
6510 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6511 @given(data_strategy())
6512 def test_sorted(self, d):
6513 class DummySeq(Sequence):
6514 schema = (("null", Null()),)
6516 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6517 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6518 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6519 tag_nums -= set([dummy_seq_tag_num])
6520 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6521 _schema.append(("seq", DummySeq()))
6524 schema = d.draw(permutations(_schema))
6526 for name, _ in _schema:
6528 seq[name] = OctetString(name.encode("ascii"))
6529 seq["seq"] = DummySeq((("null", Null()),))
6531 seq_encoded = seq.encode()
6532 seq_decoded, _ = seq.decode(seq_encoded)
6533 seq_encoded_expected = []
6534 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6535 if tag_num == dummy_seq_tag_num:
6536 seq_encoded_expected.append(seq["seq"].encode())
6538 seq_encoded_expected.append(seq[str(tag_num)].encode())
6539 self.assertSequenceEqual(
6540 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6541 b"".join(seq_encoded_expected),
6544 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6545 encoded += seq["seq"].encode()
6546 seq_encoded = b"".join((
6548 len_encode(len(encoded)),
6551 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6552 seq.decode(seq_encoded)
6553 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6554 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6555 self.assertTrue(seq_decoded.ber_encoded)
6556 self.assertTrue(seq_decoded.bered)
6557 seq_decoded = copy(seq_decoded)
6558 self.assertTrue(seq_decoded.ber_encoded)
6559 self.assertTrue(seq_decoded.bered)
6561 def test_same_value_twice(self):
6564 ("bool", Boolean()),
6568 encoded = b"".join((
6569 Integer(123).encode(),
6570 Integer(234).encode(),
6571 Boolean(True).encode(),
6573 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6574 with self.assertRaises(TagMismatch):
6575 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6579 def seqof_values_strategy(draw, schema=None, do_expl=False):
6581 schema = draw(sampled_from((Boolean(), Integer())))
6582 bound_min, bound_max = sorted(draw(sets(
6583 integers(min_value=0, max_value=10),
6587 if isinstance(schema, Boolean):
6588 values_generator = booleans().map(Boolean)
6589 elif isinstance(schema, Integer):
6590 values_generator = integers().map(Integer)
6591 values_generator = lists(
6596 values = draw(one_of(none(), values_generator))
6600 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6602 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6603 default = draw(one_of(none(), values_generator))
6604 optional = draw(one_of(none(), booleans()))
6606 draw(integers(min_value=0)),
6607 draw(integers(min_value=0)),
6608 draw(integers(min_value=0)),
6613 (bound_min, bound_max),
6622 class SeqOfMixing(object):
6623 def test_invalid_value_type(self):
6624 with self.assertRaises(InvalidValueType) as err:
6625 self.base_klass(123)
6628 def test_invalid_values_type(self):
6629 class SeqOf(self.base_klass):
6631 with self.assertRaises(InvalidValueType) as err:
6632 SeqOf([Integer(123), Boolean(False), Integer(234)])
6635 def test_schema_required(self):
6636 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6637 self.base_klass.__mro__[1]()
6639 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6640 def test_comparison(self, value1, value2, tag1, tag2):
6641 class SeqOf(self.base_klass):
6643 obj1 = SeqOf([Boolean(value1)])
6644 obj2 = SeqOf([Boolean(value2)])
6645 self.assertEqual(obj1 == obj2, value1 == value2)
6646 self.assertEqual(obj1 != obj2, value1 != value2)
6647 self.assertEqual(obj1 == list(obj2), value1 == value2)
6648 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6649 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6650 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6651 self.assertEqual(obj1 == obj2, tag1 == tag2)
6652 self.assertEqual(obj1 != obj2, tag1 != tag2)
6654 @given(lists(booleans()))
6655 def test_iter(self, values):
6656 class SeqOf(self.base_klass):
6658 obj = SeqOf([Boolean(value) for value in values])
6659 self.assertEqual(len(obj), len(values))
6660 for i, value in enumerate(obj):
6661 self.assertEqual(value, values[i])
6663 @given(data_strategy())
6664 def test_ready(self, d):
6665 ready = [Integer(v) for v in d.draw(lists(
6672 range(d.draw(integers(min_value=1, max_value=5)))
6675 class SeqOf(self.base_klass):
6677 values = d.draw(permutations(ready + non_ready))
6679 for value in values:
6681 self.assertFalse(seqof.ready)
6684 pprint(seqof, big_blobs=True, with_decode_path=True)
6685 with self.assertRaises(ObjNotReady) as err:
6688 with self.assertRaises(ObjNotReady) as err:
6690 for i, value in enumerate(values):
6691 self.assertEqual(seqof[i], value)
6692 if not seqof[i].ready:
6693 seqof[i] = Integer(i)
6694 self.assertTrue(seqof.ready)
6697 pprint(seqof, big_blobs=True, with_decode_path=True)
6699 def test_spec_mismatch(self):
6700 class SeqOf(self.base_klass):
6703 seqof.append(Integer(123))
6704 with self.assertRaises(ValueError):
6705 seqof.append(Boolean(False))
6706 with self.assertRaises(ValueError):
6707 seqof[0] = Boolean(False)
6709 @given(data_strategy())
6710 def test_bounds_satisfied(self, d):
6711 class SeqOf(self.base_klass):
6713 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6714 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6715 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6716 SeqOf(value=value, bounds=(bound_min, bound_max))
6718 @given(data_strategy())
6719 def test_bounds_unsatisfied(self, d):
6720 class SeqOf(self.base_klass):
6722 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6723 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6724 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6725 with self.assertRaises(BoundsError) as err:
6726 SeqOf(value=value, bounds=(bound_min, bound_max))
6728 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6729 SeqOf(bounds=(bound_min, bound_max)).decode(
6730 SeqOf(value).encode()
6733 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6734 SeqOf(bounds=(bound_min, bound_max)).decode(
6735 encode2pass(SeqOf(value))
6737 value = [Boolean(True)] * d.draw(integers(
6738 min_value=bound_max + 1,
6739 max_value=bound_max + 10,
6741 with self.assertRaises(BoundsError) as err:
6742 SeqOf(value=value, bounds=(bound_min, bound_max))
6744 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6745 SeqOf(bounds=(bound_min, bound_max)).decode(
6746 SeqOf(value).encode()
6749 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6750 SeqOf(bounds=(bound_min, bound_max)).decode(
6751 encode2pass(SeqOf(value))
6754 @given(integers(min_value=1, max_value=10))
6755 def test_out_of_bounds(self, bound_max):
6756 class SeqOf(self.base_klass):
6758 bounds = (0, bound_max)
6760 for _ in range(bound_max):
6761 seqof.append(Integer(123))
6762 with self.assertRaises(BoundsError):
6763 seqof.append(Integer(123))
6765 @given(data_strategy())
6766 def test_call(self, d):
6776 ) = d.draw(seqof_values_strategy())
6778 class SeqOf(self.base_klass):
6779 schema = schema_initial
6780 obj_initial = SeqOf(
6781 value=value_initial,
6782 bounds=bounds_initial,
6785 default=default_initial,
6786 optional=optional_initial or False,
6787 _decoded=_decoded_initial,
6798 ) = d.draw(seqof_values_strategy(
6799 schema=schema_initial,
6800 do_expl=impl_initial is None,
6802 if (default is None) and (obj_initial.default is not None):
6805 (bounds is None) and
6806 (value is not None) and
6807 (bounds_initial is not None) and
6808 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6812 (bounds is None) and
6813 (default is not None) and
6814 (bounds_initial is not None) and
6815 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6827 value_expected = default if value is None else value
6829 default_initial if value_expected is None
6832 value_expected = () if value_expected is None else value_expected
6833 self.assertEqual(obj, value_expected)
6834 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6835 self.assertEqual(obj.expl_tag, expl or expl_initial)
6838 default_initial if default is None else default,
6840 if obj.default is None:
6841 optional = optional_initial if optional is None else optional
6842 optional = False if optional is None else optional
6845 self.assertEqual(obj.optional, optional)
6847 (obj._bound_min, obj._bound_max),
6848 bounds or bounds_initial or (0, float("+inf")),
6851 @given(seqof_values_strategy())
6852 def test_copy(self, values):
6853 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6855 class SeqOf(self.base_klass):
6857 register_class(SeqOf)
6864 optional=optional or False,
6867 for copy_func in copy_funcs:
6868 obj_copied = copy_func(obj)
6869 self.assert_copied_basic_fields(obj, obj_copied)
6870 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6871 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6872 self.assertEqual(obj._value, obj_copied._value)
6876 integers(min_value=1).map(tag_encode),
6878 def test_stripped(self, values, tag_impl):
6879 class SeqOf(self.base_klass):
6880 schema = OctetString()
6881 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6882 with self.assertRaises(NotEnoughData):
6883 obj.decode(obj.encode()[:-1])
6887 integers(min_value=1).map(tag_ctxc),
6889 def test_stripped_expl(self, values, tag_expl):
6890 class SeqOf(self.base_klass):
6891 schema = OctetString()
6892 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6893 with self.assertRaises(NotEnoughData):
6894 obj.decode(obj.encode()[:-1])
6897 integers(min_value=31),
6898 integers(min_value=0),
6901 def test_bad_tag(self, tag, offset, decode_path):
6902 with self.assertRaises(DecodeError) as err:
6903 self.base_klass().decode(
6904 tag_encode(tag)[:-1],
6906 decode_path=decode_path,
6909 self.assertEqual(err.exception.offset, offset)
6910 self.assertEqual(err.exception.decode_path, decode_path)
6913 integers(min_value=128),
6914 integers(min_value=0),
6917 def test_bad_len(self, l, offset, decode_path):
6918 with self.assertRaises(DecodeError) as err:
6919 self.base_klass().decode(
6920 self.base_klass.tag_default + len_encode(l)[:-1],
6922 decode_path=decode_path,
6925 self.assertEqual(err.exception.offset, offset)
6926 self.assertEqual(err.exception.decode_path, decode_path)
6928 @given(binary(min_size=1))
6929 def test_tag_mismatch(self, impl):
6930 assume(impl != self.base_klass.tag_default)
6931 with self.assertRaises(TagMismatch):
6932 self.base_klass(impl=impl).decode(self.base_klass().encode())
6934 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6936 seqof_values_strategy(schema=Integer()),
6937 lists(integers().map(Integer)),
6938 integers(min_value=1).map(tag_ctxc),
6939 integers(min_value=0),
6943 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6944 _, _, _, _, _, default, optional, _decoded = values
6946 class SeqOf(self.base_klass):
6956 pprint(obj, big_blobs=True, with_decode_path=True)
6957 self.assertFalse(obj.expled)
6958 obj_encoded = obj.encode()
6959 self.assertEqual(encode2pass(obj), obj_encoded)
6960 obj_encoded_cer = encode_cer(obj)
6961 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6962 self.assertSequenceEqual(
6963 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6966 obj_expled = obj(value, expl=tag_expl)
6967 self.assertTrue(obj_expled.expled)
6969 list(obj_expled.pps())
6970 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6971 obj_expled_encoded = obj_expled.encode()
6972 ctx_copied = deepcopy(ctx_dummy)
6973 obj_decoded, tail = obj_expled.decode(
6974 obj_expled_encoded + tail_junk,
6978 self.assertDictEqual(ctx_copied, ctx_dummy)
6980 list(obj_decoded.pps())
6981 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6982 self.assertEqual(tail, tail_junk)
6983 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6984 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6985 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6986 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6988 obj_decoded.expl_llen,
6989 len(len_encode(len(obj_encoded))),
6991 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6992 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6995 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6997 self.assertEqual(obj_decoded.expl_offset, offset)
6998 for obj_inner in obj_decoded:
6999 self.assertIn(obj_inner, obj_decoded)
7000 self.assertSequenceEqual(
7003 obj_inner.offset - offset:
7004 obj_inner.offset + obj_inner.tlvlen - offset
7008 t, _, lv = tag_strip(obj_encoded)
7009 _, _, v = len_decode(lv)
7010 obj_encoded_lenindef = t + LENINDEF + v + EOC
7011 with self.assertRaises(DecodeError):
7012 obj.decode(obj_encoded_lenindef)
7013 obj_decoded_lenindef, tail_lenindef = obj.decode(
7014 obj_encoded_lenindef + tail_junk,
7015 ctx={"bered": True},
7017 self.assertTrue(obj_decoded_lenindef.lenindef)
7018 self.assertTrue(obj_decoded_lenindef.bered)
7019 obj_decoded_lenindef = copy(obj_decoded_lenindef)
7020 self.assertTrue(obj_decoded_lenindef.lenindef)
7021 self.assertTrue(obj_decoded_lenindef.bered)
7022 repr(obj_decoded_lenindef)
7023 list(obj_decoded_lenindef.pps())
7024 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
7025 self.assertEqual(tail_lenindef, tail_junk)
7026 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
7027 with self.assertRaises(DecodeError):
7028 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
7029 with self.assertRaises(DecodeError):
7030 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
7032 evgens = list(obj.decode_evgen(
7033 obj_encoded_lenindef + tail_junk,
7034 decode_path=decode_path,
7035 ctx={"bered": True},
7037 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
7038 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
7039 self.assertEqual(_decode_path, decode_path + (str(i),))
7042 _decode_path, obj, tail = evgens[-1]
7043 self.assertEqual(_decode_path, decode_path)
7047 assert_exceeding_data(
7049 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
7053 def test_bered(self):
7054 class SeqOf(self.base_klass):
7056 encoded = Boolean(False).encode()
7057 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
7058 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7059 with self.assertRaises(DecodeError):
7060 SeqOf().decode(encoded)
7061 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7062 self.assertFalse(decoded.ber_encoded)
7063 self.assertFalse(decoded.lenindef)
7064 self.assertTrue(decoded.bered)
7065 decoded = copy(decoded)
7066 self.assertFalse(decoded.ber_encoded)
7067 self.assertFalse(decoded.lenindef)
7068 self.assertTrue(decoded.bered)
7070 class SeqOf(self.base_klass):
7071 schema = OctetString()
7072 encoded = OctetString(b"whatever").encode()
7074 tag_encode(form=TagFormConstructed, num=4) +
7076 OctetString(b"whatever").encode() +
7079 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7080 with self.assertRaises(DecodeError):
7081 SeqOf().decode(encoded)
7082 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7083 self.assertFalse(decoded.ber_encoded)
7084 self.assertFalse(decoded.lenindef)
7085 self.assertTrue(decoded.bered)
7086 decoded = copy(decoded)
7087 self.assertFalse(decoded.ber_encoded)
7088 self.assertFalse(decoded.lenindef)
7089 self.assertTrue(decoded.bered)
7092 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7093 class SeqOf(SequenceOf):
7097 def _test_symmetric_compare_objs(self, obj1, obj2):
7098 self.assertEqual(obj1, obj2)
7099 self.assertSequenceEqual(list(obj1), list(obj2))
7101 def test_iterator_pickling(self):
7102 class SeqOf(SequenceOf):
7104 register_class(SeqOf)
7107 seqof = seqof(iter(six_xrange(10)))
7108 with assertRaisesRegex(self, ValueError, "iterator"):
7111 def test_iterator_bounds(self):
7112 class SeqOf(SequenceOf):
7118 for i in six_xrange(n):
7121 seqof = SeqOf(gen(n))
7122 self.assertTrue(seqof.ready)
7123 with self.assertRaises(BoundsError):
7125 self.assertFalse(seqof.ready)
7126 seqof = seqof(gen(n))
7127 self.assertTrue(seqof.ready)
7128 with self.assertRaises(BoundsError):
7130 self.assertFalse(seqof.ready)
7132 def test_iterator_twice(self):
7133 class SeqOf(SequenceOf):
7135 bounds = (1, float("+inf"))
7138 for i in six_xrange(10):
7140 seqof = SeqOf(gen())
7141 self.assertTrue(seqof.ready)
7143 self.assertFalse(seqof.ready)
7144 register_class(SeqOf)
7147 def test_iterator_2pass(self):
7148 class SeqOf(SequenceOf):
7150 bounds = (1, float("+inf"))
7153 for i in six_xrange(10):
7155 seqof = SeqOf(gen())
7156 self.assertTrue(seqof.ready)
7157 _, state = seqof.encode1st()
7158 self.assertFalse(seqof.ready)
7159 seqof = seqof(gen())
7160 self.assertTrue(seqof.ready)
7162 seqof.encode2nd(buf.write, iter(state))
7163 self.assertSequenceEqual(
7164 [int(i) for i in seqof.decod(buf.getvalue())],
7168 def test_non_ready_bound_min(self):
7169 class SeqOf(SequenceOf):
7171 bounds = (1, float("+inf"))
7173 self.assertFalse(seqof.ready)
7176 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7181 def _test_symmetric_compare_objs(self, obj1, obj2):
7182 self.assertSetEqual(
7183 set(int(v) for v in obj1),
7184 set(int(v) for v in obj2),
7187 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7188 @given(data_strategy())
7189 def test_sorted(self, d):
7190 values = [OctetString(v) for v in d.draw(lists(binary()))]
7193 schema = OctetString()
7195 seq_encoded = seq.encode()
7196 seq_decoded, _ = seq.decode(seq_encoded)
7197 self.assertSequenceEqual(
7198 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7199 b"".join(sorted([v.encode() for v in values])),
7202 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7203 @given(data_strategy())
7204 def test_unsorted(self, d):
7205 values = [OctetString(v).encode() for v in d.draw(sets(
7206 binary(min_size=1, max_size=5),
7210 values = d.draw(permutations(values))
7211 assume(values != sorted(values))
7212 encoded = b"".join(values)
7213 seq_encoded = b"".join((
7215 len_encode(len(encoded)),
7220 schema = OctetString()
7222 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7223 seq.decode(seq_encoded)
7225 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7226 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7227 self.assertTrue(seq_decoded.ber_encoded)
7228 self.assertTrue(seq_decoded.bered)
7229 seq_decoded = copy(seq_decoded)
7230 self.assertTrue(seq_decoded.ber_encoded)
7231 self.assertTrue(seq_decoded.bered)
7232 self.assertSequenceEqual(
7233 [obj.encode() for obj in seq_decoded],
7238 class TestGoMarshalVectors(TestCase):
7240 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7241 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7242 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7243 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7244 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7246 class Seq(Sequence):
7248 ("erste", Integer()),
7249 ("zweite", Integer(optional=True))
7252 seq["erste"] = Integer(64)
7253 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7254 seq["erste"] = Integer(0x123456)
7255 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7256 seq["erste"] = Integer(64)
7257 seq["zweite"] = Integer(65)
7258 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7260 class NestedSeq(Sequence):
7264 seq["erste"] = Integer(127)
7265 seq["zweite"] = None
7266 nested = NestedSeq()
7267 nested["nest"] = seq
7268 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7270 self.assertSequenceEqual(
7271 OctetString(b"\x01\x02\x03").encode(),
7272 hexdec("0403010203"),
7275 class Seq(Sequence):
7277 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7280 seq["erste"] = Integer(64)
7281 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7283 class Seq(Sequence):
7285 ("erste", Integer(expl=tag_ctxc(5))),
7288 seq["erste"] = Integer(64)
7289 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7291 class Seq(Sequence):
7294 impl=tag_encode(0, klass=TagClassContext),
7299 seq["erste"] = Null()
7300 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7302 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7304 self.assertSequenceEqual(
7305 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7306 hexdec("170d3730303130313030303030305a"),
7308 self.assertSequenceEqual(
7309 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7310 hexdec("170d3039313131353232353631365a"),
7312 self.assertSequenceEqual(
7313 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7314 hexdec("180f32313030303430353132303130315a"),
7317 class Seq(Sequence):
7319 ("erste", GeneralizedTime()),
7322 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7323 self.assertSequenceEqual(
7325 hexdec("3011180f32303039313131353232353631365a"),
7328 self.assertSequenceEqual(
7329 BitString((1, b"\x80")).encode(),
7332 self.assertSequenceEqual(
7333 BitString((12, b"\x81\xF0")).encode(),
7334 hexdec("03030481f0"),
7337 self.assertSequenceEqual(
7338 ObjectIdentifier("1.2.3.4").encode(),
7339 hexdec("06032a0304"),
7341 self.assertSequenceEqual(
7342 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7343 hexdec("06092a864888932d010105"),
7345 self.assertSequenceEqual(
7346 ObjectIdentifier("2.100.3").encode(),
7347 hexdec("0603813403"),
7350 self.assertSequenceEqual(
7351 PrintableString("test").encode(),
7352 hexdec("130474657374"),
7354 self.assertSequenceEqual(
7355 PrintableString("x" * 127).encode(),
7356 hexdec("137F" + "78" * 127),
7358 self.assertSequenceEqual(
7359 PrintableString("x" * 128).encode(),
7360 hexdec("138180" + "78" * 128),
7362 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7364 class Seq(Sequence):
7366 ("erste", IA5String()),
7369 seq["erste"] = IA5String("test")
7370 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7372 class Seq(Sequence):
7374 ("erste", PrintableString()),
7377 seq["erste"] = PrintableString("test")
7378 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7379 # Asterisk is actually not allowable
7380 PrintableString._allowable_chars |= set(b"*")
7381 seq["erste"] = PrintableString("test*")
7382 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7383 PrintableString._allowable_chars -= set(b"*")
7385 class Seq(Sequence):
7387 ("erste", Any(optional=True)),
7388 ("zweite", Integer()),
7391 seq["zweite"] = Integer(64)
7392 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7397 seq.append(Integer(10))
7398 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7400 class _SeqOf(SequenceOf):
7401 schema = PrintableString()
7403 class SeqOf(SequenceOf):
7406 _seqof.append(PrintableString("1"))
7408 seqof.append(_seqof)
7409 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7411 class Seq(Sequence):
7413 ("erste", Integer(default=1)),
7416 seq["erste"] = Integer(0)
7417 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7418 seq["erste"] = Integer(1)
7419 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7420 seq["erste"] = Integer(2)
7421 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7424 class TestPP(TestCase):
7425 @given(data_strategy())
7426 def test_oid_printing(self, d):
7428 str(ObjectIdentifier(k)): v * 2
7429 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7431 chosen = d.draw(sampled_from(sorted(oids)))
7432 chosen_id = oids[chosen]
7433 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7434 self.assertNotIn(chosen_id, pp_console_row(pp))
7437 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7441 class TestAutoAddSlots(TestCase):
7443 class Inher(Integer):
7446 with self.assertRaises(AttributeError):
7448 inher.unexistent = "whatever"
7451 class TestOIDDefines(TestCase):
7452 @given(data_strategy())
7453 def runTest(self, d):
7454 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7455 value_name_chosen = d.draw(sampled_from(value_names))
7457 ObjectIdentifier(oid)
7458 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7460 oid_chosen = d.draw(sampled_from(oids))
7461 values = d.draw(lists(
7463 min_size=len(value_names),
7464 max_size=len(value_names),
7466 for definable_class in (Any, OctetString, BitString):
7468 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7469 oid: Integer() for oid in oids[:-1]
7472 for i, value_name in enumerate(value_names):
7473 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7475 class Seq(Sequence):
7478 for value_name, value in zip(value_names, values):
7479 seq[value_name] = definable_class(Integer(value).encode())
7480 seq["type"] = oid_chosen
7481 seq, _ = Seq().decode(seq.encode())
7482 for value_name in value_names:
7483 if value_name == value_name_chosen:
7485 self.assertIsNone(seq[value_name].defined)
7486 if value_name_chosen in oids[:-1]:
7487 self.assertIsNotNone(seq[value_name_chosen].defined)
7488 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7489 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7492 pprint(seq, big_blobs=True, with_decode_path=True)
7495 class TestDefinesByPath(TestCase):
7496 def test_generated(self):
7497 class Seq(Sequence):
7499 ("type", ObjectIdentifier()),
7500 ("value", OctetString(expl=tag_ctxc(123))),
7503 class SeqInner(Sequence):
7505 ("typeInner", ObjectIdentifier()),
7506 ("valueInner", Any()),
7509 class PairValue(SetOf):
7512 class Pair(Sequence):
7514 ("type", ObjectIdentifier()),
7515 ("value", PairValue()),
7518 class Pairs(SequenceOf):
7525 type_octet_stringed,
7527 ObjectIdentifier(oid)
7528 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7530 seq_integered = Seq()
7531 seq_integered["type"] = type_integered
7532 seq_integered["value"] = OctetString(Integer(123).encode())
7533 seq_integered_raw = seq_integered.encode()
7537 (type_octet_stringed, OctetString(b"whatever")),
7538 (type_integered, Integer(123)),
7539 (type_octet_stringed, OctetString(b"whenever")),
7540 (type_integered, Integer(234)),
7542 for t, v in pairs_input:
7545 ("value", PairValue((Any(v),))),
7547 seq_inner = SeqInner()
7548 seq_inner["typeInner"] = type_innered
7549 seq_inner["valueInner"] = Any(pairs)
7550 seq_sequenced = Seq()
7551 seq_sequenced["type"] = type_sequenced
7552 seq_sequenced["value"] = OctetString(seq_inner.encode())
7553 seq_sequenced_raw = seq_sequenced.encode()
7555 list(seq_sequenced.pps())
7556 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7558 defines_by_path = []
7559 ctx_copied = deepcopy(ctx_dummy)
7560 seq_integered, _ = Seq().decode(
7564 self.assertDictEqual(ctx_copied, ctx_dummy)
7565 self.assertIsNone(seq_integered["value"].defined)
7566 defines_by_path.append(
7567 (("type",), ((("value",), {
7568 type_integered: Integer(),
7569 type_sequenced: SeqInner(),
7572 ctx_copied["defines_by_path"] = defines_by_path
7573 seq_integered, _ = Seq().decode(
7577 del ctx_copied["defines_by_path"]
7578 self.assertDictEqual(ctx_copied, ctx_dummy)
7579 self.assertIsNotNone(seq_integered["value"].defined)
7580 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7581 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7582 self.assertTrue(seq_integered_raw[
7583 seq_integered["value"].defined[1].offset:
7584 ].startswith(Integer(123).encode()))
7586 list(seq_integered.pps())
7587 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7589 ctx_copied["defines_by_path"] = defines_by_path
7590 seq_sequenced, _ = Seq().decode(
7594 del ctx_copied["defines_by_path"]
7595 self.assertDictEqual(ctx_copied, ctx_dummy)
7596 self.assertIsNotNone(seq_sequenced["value"].defined)
7597 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7598 seq_inner = seq_sequenced["value"].defined[1]
7599 self.assertIsNone(seq_inner["valueInner"].defined)
7601 list(seq_sequenced.pps())
7602 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7604 defines_by_path.append((
7605 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7606 ((("valueInner",), {type_innered: Pairs()}),),
7608 ctx_copied["defines_by_path"] = defines_by_path
7609 seq_sequenced, _ = Seq().decode(
7613 del ctx_copied["defines_by_path"]
7614 self.assertDictEqual(ctx_copied, ctx_dummy)
7615 self.assertIsNotNone(seq_sequenced["value"].defined)
7616 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7617 seq_inner = seq_sequenced["value"].defined[1]
7618 self.assertIsNotNone(seq_inner["valueInner"].defined)
7619 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7620 pairs = seq_inner["valueInner"].defined[1]
7622 self.assertIsNone(pair["value"][0].defined)
7624 list(seq_sequenced.pps())
7625 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7627 defines_by_path.append((
7630 DecodePathDefBy(type_sequenced),
7632 DecodePathDefBy(type_innered),
7637 type_integered: Integer(),
7638 type_octet_stringed: OctetString(),
7641 ctx_copied["defines_by_path"] = defines_by_path
7642 seq_sequenced, _ = Seq().decode(
7646 del ctx_copied["defines_by_path"]
7647 self.assertDictEqual(ctx_copied, ctx_dummy)
7648 self.assertIsNotNone(seq_sequenced["value"].defined)
7649 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7650 seq_inner = seq_sequenced["value"].defined[1]
7651 self.assertIsNotNone(seq_inner["valueInner"].defined)
7652 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7653 pairs_got = seq_inner["valueInner"].defined[1]
7654 for pair_input, pair_got in zip(pairs_input, pairs_got):
7655 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7656 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7658 list(seq_sequenced.pps())
7659 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7661 @given(oid_strategy(), integers())
7662 def test_simple(self, oid, tgt):
7663 class Inner(Sequence):
7665 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7666 ObjectIdentifier(oid): Integer(),
7670 class Outer(Sequence):
7673 ("tgt", OctetString()),
7677 inner["oid"] = ObjectIdentifier(oid)
7679 outer["inner"] = inner
7680 outer["tgt"] = OctetString(Integer(tgt).encode())
7681 decoded, _ = Outer().decode(outer.encode())
7682 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7684 def test_remaining_data(self):
7685 oid = ObjectIdentifier("1.2.3")
7687 class Seq(Sequence):
7689 ("oid", ObjectIdentifier(defines=((("tgt",), {
7692 ("tgt", OctetString()),
7697 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7699 with assertRaisesRegex(self, DecodeError, "remaining data"):
7700 Seq().decode(seq.encode())
7702 def test_remaining_data_seqof(self):
7703 oid = ObjectIdentifier("1.2.3")
7706 schema = OctetString()
7708 class Seq(Sequence):
7710 ("oid", ObjectIdentifier(defines=((("tgt",), {
7718 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7720 with assertRaisesRegex(self, DecodeError, "remaining data"):
7721 Seq().decode(seq.encode())
7724 class TestAbsDecodePath(TestCase):
7726 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7727 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7729 def test_concat(self, decode_path, rel_path):
7730 dp = abs_decode_path(decode_path, rel_path)
7731 self.assertSequenceEqual(dp, decode_path + rel_path)
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_abs(self, decode_path, rel_path):
7739 self.assertSequenceEqual(
7740 abs_decode_path(decode_path, ("/",) + rel_path),
7745 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7746 integers(min_value=1, max_value=3),
7747 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7749 def test_dots(self, decode_path, number_of_dots, rel_path):
7750 self.assertSequenceEqual(
7751 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7752 decode_path[:-number_of_dots] + rel_path,
7756 class TestStrictDefaultExistence(TestCase):
7757 @given(data_strategy())
7758 def runTest(self, d):
7759 count = d.draw(integers(min_value=1, max_value=10))
7760 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7762 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7763 for i in range(count)
7765 for klass in (Sequence, Set):
7769 for i in range(count):
7770 seq["int%d" % i] = Integer(123)
7772 chosen_choice = "int%d" % chosen
7773 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7774 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7776 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7777 self.assertTrue(decoded.ber_encoded)
7778 self.assertTrue(decoded.bered)
7779 decoded = copy(decoded)
7780 self.assertTrue(decoded.ber_encoded)
7781 self.assertTrue(decoded.bered)
7782 decoded, _ = seq.decode(raw, ctx={"bered": True})
7783 self.assertTrue(decoded.ber_encoded)
7784 self.assertTrue(decoded.bered)
7785 decoded = copy(decoded)
7786 self.assertTrue(decoded.ber_encoded)
7787 self.assertTrue(decoded.bered)
7790 class TestX690PrefixedType(TestCase):
7792 self.assertSequenceEqual(
7793 VisibleString("Jones").encode(),
7794 hexdec("1A054A6F6E6573"),
7798 self.assertSequenceEqual(
7801 impl=tag_encode(3, klass=TagClassApplication),
7803 hexdec("43054A6F6E6573"),
7807 self.assertSequenceEqual(
7811 impl=tag_encode(3, klass=TagClassApplication),
7815 hexdec("A20743054A6F6E6573"),
7819 self.assertSequenceEqual(
7823 impl=tag_encode(3, klass=TagClassApplication),
7825 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7827 hexdec("670743054A6F6E6573"),
7831 self.assertSequenceEqual(
7832 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7833 hexdec("82054A6F6E6573"),
7837 class TestExplOOB(TestCase):
7839 expl = tag_ctxc(123)
7840 raw = Integer(123).encode() + Integer(234).encode()
7841 raw = b"".join((expl, len_encode(len(raw)), raw))
7842 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7843 Integer(expl=expl).decode(raw)
7844 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7847 class TestPickleDifferentVersion(TestCase):
7849 pickled = pickle_dumps(Integer(123), pickle_proto)
7851 version_orig = pyderasn.__version__
7852 pyderasn.__version__ += "different"
7853 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7854 pickle_loads(pickled)
7855 pyderasn.__version__ = version_orig
7856 pickle_loads(pickled)
7859 class TestCERSetOrdering(TestCase):
7860 def test_vectors(self):
7861 """Taken from X.690-201508
7865 ("c", Integer(impl=tag_ctxp(2))),
7866 ("d", Integer(impl=tag_ctxp(4))),
7871 ("g", Integer(impl=tag_ctxp(5))),
7872 ("h", Integer(impl=tag_ctxp(6))),
7877 ("j", Integer(impl=tag_ctxp(0))),
7888 ("a", Integer(impl=tag_ctxp(3))),
7889 ("b", B(expl=tag_ctxc(1))),
7894 ("a", Integer(123)),
7895 ("b", B(("d", Integer(234)))),
7896 ("e", E(("f", F(("g", Integer(345)))))),
7898 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7899 self.assertSequenceEqual(
7900 [i.__class__.__name__ for i in order],
7901 ("E", "B", "Integer"),